「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
目次  †
概要  †
特徴  †
モジュラーデザイン  †
ユースケースに対応するため、
- 複数の仕様から成り立っており、
 
- それらをモジュール的に組み合わせることで
 
多様な環境をサポートできる。
プロトコル概要  †
ざっくり、リクエスト→認証・認可→ユーザ情報を取得。
+--------+                                   +--------+
|        |                                   |        |
|        |---------(1) AuthN Request-------->|        |
|        |                                   |        |
|        |  +--------+                       |        |
|        |  |        |                       |        |
|        |  |  End-  |<--(2) AuthN & AuthZ-->|        |
|        |  |  User  |                       |        |
|   RP   |  |        |                       |   OP   |
|        |  +--------+                       |        |
|        |                                   |        |
|        |<--------(3) AuthN Response--------|        |
|        |                                   |        |
|        |---------(4) UserInfo Request----->|        |
|        |                                   |        |
|        |<--------(5) UserInfo Response-----|        |
|        |                                   |        |
+--------+                                   +--------+
OAuth 2.0との違いは、認証拡張機能が実装された点にある。
- OAuth 2.0では
- 認証機能(「認証Endpointからユーザー属性クレーム群を取得する」)の仕様が無かった。
 
- このため、この部分の拡張仕様(認証Endpoint)に方言があり、実装上問題だった。
 
 
- OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜
 
仕様一覧  †
- Final: OpenID Connect Core 1.0 incorporating errata set 1
 
仕様の柱  †
Client Implementer's Guide  †
- OAuth 2.0に認証結果とプロフィールの受渡し機能のみを追加、
 
- 以下は、WebアプリケーションのClientに当該フローを実装する場合の実装ガイド。
 
- OpenID Connect Client Implementer's Guide
 
関連仕様  †
認証のシーケンス  †
Authorization Code Flow  †
概要  †
OAuth 2.0 からのステップ上の拡張部分は無い。
ただし、アクセス先がResources ServerのEndpointがユーザー情報エンドポイントに特定されており、
ここから、認証されたユーザ情報としてユーザー属性クレーム群を取得している。
ステップ  †
The Authorization Code Flow goes through the following steps.
- Client prepares an Authentication Request containing the desired request parameters.
 
- Client sends the request to the Authorization Server.
 
- Authorization Server Authenticates the End-User.
 
- Authorization Server obtains End-User Consent/Authorization.
 
- Authorization Server sends the End-User back to the Client with an Authorization Code.
 
- Client requests a response using the Authorization Code at the Token Endpoint.
 
- Client receives a response that contains an ID Token and Access Token in the response body.
 
- Client validates the ID token and retrieves the End-User's Subject Identifier.
 
Implicit Flow  †
概要  †
朱書きは、OAuth 2.0 からのステップ上の変更・拡張部分。
ポイントは、User-Agentやスマホネイティブから直接的にAccess Tokenを使用せず、
ClientにAccess Tokenを送って、そこからユーザー属性クレーム群を取得している点。
ステップ  †
The Implicit Flow follows the following steps:
- Client prepares an Authentication Request containing the desired request parameters.
 
- Client sends the request to the Authorization Server.
 
- Authorization Server Authenticates the End-User.
 
- Authorization Server obtains End-User Consent/Authorization.
 
- Authorization Server sends the End-User back to the Client with an ID Token and, if requested, an Access Token.
 
- Client validates the ID token and retrieves the End-User's Subject Identifier.
 
Hybrid Flow  †
概要  †
朱書きは、Authorization Code Flowとの差異。
ID トークンと同時に、アクセストークンや認可コードが一緒に発行される場合、
ID トークンにat_hash、c_hashクレームが追加される(用途不明)。
ステップ  †
The Hybrid Flow follows the following steps:
- Client prepares an Authentication Request containing the desired request parameters.
 
- Client sends the request to the Authorization Server.
 
- Authorization Server Authenticates the End-User.
 
- Authorization Server obtains End-User Consent/Authorization.
 
- Authorization Server sends the End-User back to the Client with an Authorization Code and,
depending on the Response Type, one or more additional parameters. 
- Client requests a response using the Authorization Code at the Token Endpoint.
 
- Client receives a response that contains an ID Token and Access Token in the response body.
 
- Client validates the ID Token and retrieves the End-User's Subject Identifier.
 
IDトークン  †
概要  †
- 発行元のIdp(OP)識別子
 
- 発行先のRP識別子(client_id)
 
- ユーザー識別子
 
- 発行日時
 
- クレームの扱いについて次のような機能を定義している。
 
- クレームの暗号化(Encrypted Claims)
 
メッセージ形式にJSONを採用  †
JWT : JSON Web Tokenの略
クレーム暗号化  †
JWTのJWS or JWEを使用する。
クレームセット  †
必須クレーム群  †
- iss (issuer) クレーム
- (OAuth 2.0で言う所の)Authorization Serverの識別子。
 
- URI形式が推奨
これは、OpenID Connect Discovery 1.0 仕様をサポートするのであれば、
「{issクレームの値}/.well-known/openid-configuration」という URL で
リクエストを受け付ける必要があるため。 
 
- sub (subject) クレーム
ユーザーテーブルのプライマリーキーやそれに準ずるもの。 
- aud (audience) クレーム
(OAuth 2.0で言う所の)クライアント識別子。 
- exp (expiration time) クレーム
- JWT の有効期限
 
- Unix エポックからの経過秒数(ミリ秒ではなく秒)
 
 
- iat (issued at)クレーム
- JWT の発行日時
 
- Unix エポックからの経過秒数(ミリ秒ではなく秒)
 
 
ケースバイケースなクレーム群  †
- auth_time クレーム
- ユーザー認証時刻
 
- Unix エポックからの経過秒数(ミリ秒ではなく秒)
 
- リクエストパラメータやメタ情報設定次第で必須となるもよう。
 
 
- nonce クレーム
- リプレイアタック防止を目的とするクレーム。
 
- ID トークン発行依頼に付属するnonce 値を、そのまま埋め込む。
 
- Implicit Flowの場合は必須となるもよう。
 
 
オプションのクレーム群  †
- acr クレーム
- 認証コンテキストのクラス
 
- 必要に応じて再認証を催す。
 
- 仕様で幾つか定義されているらしいが詳細不明。
 
 
- amr クレーム
- 認証手法を示す。
 
- 利用用途が不明。
 
- 仕様範囲外、クレームの利用者が規則を決めて運用する。
 
 
- azp クレーム
- 認可された対象者
 
- 認証されたユーザと認可されたユーザが違うケースを想定している模様。
 
 
外部クレーム  †
Idp(OP)は、扱うクレームの内容によって、
どちらを利用すべきかを判断する必要がある。
集約クレーム(Aggregated Claims)  †
- 別のIdp(OP)が持つクレームを署名付きで提供すること。
 
- RPからリクエストを受けたIdp(OP)は、事前に取得していた、
もしくは動的に取得した別のIdp(OP)のクレームをレスポンスに含む。 
一定期間変更されないことが保証されており
キャッシュの効果があるものは集約クレーム。
分散クレーム(Distributed Claims)  †
クレームそのものではなく、問い合わせ先のURLを扱う。
- ユーザー認可が必要な場合
- エンドポイントのURL
 
- OAuth 2.0のアクセストークン
 
 
をレスポンスに含む。
頻繁に更新されるものは分散クレーム。
Google  †
GoogleでOpenID Connectの認証で取得したクレームセット。
(id_tokenそのものなのか?、ユーザー情報エンドポイントから取得したクレームか?)
{
  "iss":"accounts.google.com",
  "at_hash":"・・・", ← Hybrid Flowの追加クレーム
  "email_verified":"true",
  "sub":"ユーザーの一意識別子",
  "azp":"認可された対象者のID.apps.googleusercontent.com",
  "email":"・・・・",
  "aud":"クライアント識別子.apps.googleusercontent.com",
  "iat":JWT の発行日時(Unix時間),
  "exp":JWT の有効期限(Unix時間)
}
ココを見ると、これは恐らく、id_tokenなのだろうなと。
以下のGoogle公式のマニュアルにも記載があった。
ユーザー属性クレーム群  †
Standard Claims  †
| 項番 | グループ名 | 意味 | 
 | クレーム名 | 
| 1 | sub | ユーザーの一意識別子 | 
| 2 | profile | プロフィール | 
| 2-1 | name | フルネーム | 
| 2-2 | given_name | 名 | 
| 2-3 | family_name | 姓 | 
| 2-4 | middle_name | ミドルネーム | 
| 2-5 | nickname | ニックネーム | 
| 2-6 | preferred_username | 好みのユーザー名 | 
| 2-7 | profile | プロフィールページの URL | 
| 2-8 | picture | プロフィール画像の URL | 
| 2-9 | website | Web サイトやブログの URL | 
| 2-10 | gender | 性別。female と male が定義済み。 | 
| 2-11 | birthdate | 誕生日。YYYY-MM-DD。 | 
| 2-12 | zoneinfo | タイムゾーン。Europe/Paris など。 | 
| 2-13 | locale | ロケール。en-US など。 | 
| 2-14 | updated_at | 情報最終更新日。Unix エポックからの経過秒数。 | 
| 3 | email | 電子メール | 
| 3-1 |  | email | 電子メールアドレス | 
| 3-2 |  | email_verified | 電子メールアドレスが検証済みか否かの真偽値 | 
| 4 | phone | 電話 | 
| 4-1 |  | phone_number | 電話番号 | 
| 4-2 |  | phone_number_verified | 電話番号が検証済みか否かの真偽値 | 
| 5 | address | 住所 JSON object。書式は「5.1.1. Address Claim」に記載。 | 
| 5-1 |  | formatted | フォーマットされたフルメールアドレス、表示用・郵送用に使用 | 
| 5-2 |  | street_address | 通り・番地、号室、私書箱、複数行の拡張された住所情報。 | 
| 5-3 |  | locality | City or locality | 
| 5-4 |  | region | State, province, prefecture, or region. | 
| 5-5 |  | postal_code | Zip code or postal code | 
| 5-6 |  | country | Country name | 
 
多言語化  †
- クレームによっては多言語化可能
 
- クレーム名に続いて"#ja-Kana-JP"などの言語タグを付与する。
 
ユーザー属性クレーム群の格納要求  †
scope値による格納要求  †
scope値によってユーザー属性クレーム群の格納要求を行うことができる。
グループ名  †
前述のグループ名をscope値に指定可能。
格納部位  †
- UserInfo?エンドポイントからUserInfo?レスポンス(JSON オブジェクト)として返される.
 
- response_type 値が id_token の場合、
- この場合、Access Token が発行されない。
 
- ユーザー属性クレーム群はID Token で返却される。
 
 
クレーム要求JSONによる格納要求  †
- クレームをリスト化したJSON オブジェクトを使用して特定のクレームの返却を要求する。
 
トップレベルメンバ  †
- userinfoメンバ
- OPTIONAL.
 
- UserInfo?エンドポイントへ返却を要求する個々のクレームのリスト。
 
 
- 当メンバが存在した場合、
- scope 値で要求されたクレームに加え、
 
- 当メンバでリストされたクレームも返却される。
 
 
- 当メンバーが存在しなかった場合、
- scope 値で要求されたクレームのみが返却される。
 
- userinfoメンバを指定する際は、UserInfo? Endpoint を使用するために、
response_type に対し, Access Token を Client に発行するタイプの値を指定しなければならない。 
 
- id_tokenメンバ
- OPTIONAL.
 
- ID トークン内に格納して返却を要求する個々のクレームのリストを示す。
 
 
- 当メンバーが存在した場合、
- デフォルトのクレームに加え
 
- 当メンバーでリストされたクレームも返却される。
 
 
クレーム要求JSONの例  †
クレーム要求JSONの例を以下に示す:
 {
  "userinfo":
   {
    "given_name": {"essential": true},
    "nickname": null,
    "email": {"essential": true},
    "email_verified": {"essential": true},
    "picture": null,
    "http://example.info/claims/groups": null
   },
  "id_token":
   {
    "auth_time": {"essential": true},
    "acr": {"values": ["urn:mace:incommon:iap:silver"] }
   }
 }
ユーザー情報エンドポイント  †
概要  †
- OAuth 2.0のResource ServerのWebAPI
 
- HTTP的には、HTTPS必須
 
リクエスト  †
- HTTP の GET と POST メソッドをサポートする。
 
レスポンス  †
- UserInfo?レスポンスは JSON オブジェクトとして返される。
- UserInfo?クレームは JSON オブジェクトのメンバーとして返される。
 
- UserInfo?レスポンスのクレームセットには、必ず sub (subject) クレームを含める。
 
- ユーザー属性クレーム群に加え、そこに明記されていないクレームも返却可能。
 
- Idp(OP)は要求された クレームの値を、必ずしも返さなくてもよい。
 
- クレームが返されない場合、null や空文字列ではなく、JSON オブジェクトのメンバーから除かれるべき。
 
 
- JWTによる署名 or 暗号化、若しくは、署名 and 暗号化を行う場合
- Claim は JWT で返されるため、Content-Type は application/jwtとする。
 
- 署名する場合、subに加え、iss (issuer) Claim と aud (audience) Claim を含むべき。
 
- 署名と暗号化の両方が要求された場合、レスポンスは JWT で定義されているように、
結果はネストされた JWT となり、 署名した後に暗号化しなければならない。 
 
- 以下に UserInfo?レスポンスの一例を示す:
 HTTP/1.1 200 OK
 Content-Type: application/json
 {
   "sub": "ユーザID 的 な情報",
   "name": "Jane Doe",
   "given_name": "Jane",
   "family_name": "Doe",
   "preferred_username": "j.doe",
   "email": "janedoe@techinfoofmicrosofttech.osscons.jp",
   "picture": "http://techinfoofmicrosofttech.osscons.jp/janedoe/me.jpg"
 } 
- クライアントによるUserInfo?レスポンスの検証
- TLS サーバー証明書チェックを通じてIdp(OP)を検証する。
 
- UserInfo?レスポンスがJWTの場合、署名検証や復号化を行う。
 
- ID トークンとUserInfo?クレームのsubが一致することを検証する必要がある。
 
 
この仕様は、Discovery、Dynamic Client Registrationと関係がある。
OpenID Connectのシーケンス  †
STEP 0 は事前準備なので、STEP 1 からが実際の認証・認可のシーケンス。
Webアプリ(Basic Client Profile)  †
- Basic Client Profile:OAuth 2.0 Authorization Code Grantを拡張
 
STEP 0 : 事前準備(Idp(OP)にRPを登録)  †
Idp(OP)にRPを登録し、
- アプリケーションID(client_id)
 
- シークレット(client_secret)
 
を入手する。
STEP 1 : Authorization codeの取得  †
RPがIdp(OP)からAuthorization codeを取得。
- パラメタ
| パラメータ | 必須 | 説明 | 
| response_type | ○ | 「code」と「id_token」を指定 | 
| client_id | ○ | 事前に準備したclient_idの値を指定 | 
| redirect_uri | ○ | アプリケーションID登録時のコールバックURLに入力したURLを指定 | 
| state |  | CSRF対策のランダム文字列を指定 | 
| scope | ○ | ・openid:ユーザー識別子を取得(必須) ・profile:姓名・生年・性別が取得 ・email:メールアドレスと確認済みフラグを取得 ・address:ユーザー登録住所情報が取得 | 
| nonce | id_tokenを取得する際は必須 | リプレイアタック対策のランダム文字列を指定 | 
| display |  | ユーザのUIを選択: ・page(PC用UI、デフォルト値) ・touch(スマートフォン用UI) ・wap(フィーチャーフォン用UI) ・inapp(ネイティブアプリ用UI)~ | 
| その他、Idp(OP)独自パラメタ |  | - | 
 
- 成功するとログイン/同意画面が表示される。
一度同意すると、次回以降同意画面は省略される。 
- ”code=xxxxxxxx”が、Authorization codeなので保存する。
 
- ”state=CSRF対策のランダム文字列”が、一致していることを確認する。
 
STEP 2 : Access Token、ID Tokenの取得  †
- Tokenを取得する際は、POSTでリクエストを送信(HTTPリクエストのヘッダーやデータにTokenリクエストに必要な値を指定する必要がある)ため、CUIのcURLコマンドを使用して、Access Token、ID Tokenを取得する。
 
- cURLコマンドなどでリクエストする。
- Header:'Authorization: Basic {basicAuth}'
 
- URL:https://・・・Idp(OP)のAccess Token、ID Token取得用のURL・・・?grant_type=authorization_code&code=・・・&redirect_uri=・・・"
| パラメータ | 必須 | 説明 | 
| grant_type | ○ | authorization_code という固定文字列を指定 | 
| code | ○ | Authorization codeを指定、リクエスト送信後は使用できなくなる。 | 
| redirect_uri | ○ | STEP 1 のredirect_uriで指定したURLを入力。 | 
 
 
- 基本認証が必要になる。
- アプリケーションID(client_id)
 
- シークレット(client_secret)
 
- 上記を":"区切りで結合しBase64文字列化
 
 
- 以下の様なレスポンスが返る。
{
    "access_token":"{ヘッダー部}.{ペイロード部}.{シグネチャー部}",
    "token_type":"bearer",
    "expires_in":"3600",
    "refresh_token":"・・・",
    "id_token":"・・・"
} 
STEP 3 : ID トークンの正当性の検証  †
"access_token"の
- {ペイロード部}を取り出して、base64デコード。
{
    "iss":"https:\/\/・・・Access Tokenの発行元URL・・・",
    "user_id":"ユーザー識別子",
    "aud":"アプリケーションID(client_id)と一致する値",
    "iat":IDトークンの発行時刻,
    "exp":IDトークンの有効期限,
    "nonce":"STEP 1 のnonceと一致する値"
} 
- 署名の検証
- "{ヘッダー部}.{ペイロード部}"を使用して,alg:HMAC-SHA256でバイナリ形式でハッシュ化。
 
- それをBase64文字列化した文字列が"{シグネチャー部}"と一致していることを確認する。
 
 
STEP 4 : 属性情報の取得  †
- RPがIdP(OP)で認証したユーザ属性情報を取得する。
 
- ここで、準備、STEP 0-3 で取得したAccess Tokenを使う。
 
- ユーザー情報エンドポイントに、以下の形式でAccess Tokenを渡す。
- Header:'Authorization: Bearer {access_token}'
 
- URL:https://・・・ユーザ属性情報の発行元URL・・・?schema=openid
 
 
- 以下のユーザ属性情報を含んだクレームが取得できる。
{
    "user_id":"・・・",
    "name":"・・・",
    "given_name":"・・・",
    "given_name#ja-Kana-JP":"・・・",
    "given_name#ja-Hani-JP":"・・・",
    "family_name":"・・・",
    "family_name#ja-Kana-JP":"・・・",
    "family_name#ja-Hani-JP":"・・・",
    "gender":"male or female",
    "birthday":"YYYY",
    "locale":"ja-JP,etc."
} 
モバイルアプリ(Implicit Client Profile)  †
- Implicit Client Profile:OAuth 2.0 Implicit Grantを拡張
 
- Webアプリ(Basic Client Profile)との違い
- STEP 0は、前提の違いによる差異。
 
- STEP 1以降は、Implicit Flowがベースとなっている。
 
 
STEP 0 : Discovery & Dynamic Client Registration  †
IdP(OP)探索と動的なRP登録
- 「○○のIDでログイン」というリンクを選択する替わりに、
次の2種類の値をIdP(OP)特定(Discovery)のためのヒントとして利用できる。
 
- 動的なRP登録
RP登録用エンドポイントにPOSTリクエストを送ることで、
動的なRP登録(Dynamic Client Registration)もできる。 
結果的に、OPからRP識別のための“cient_id”がレスポンスされる。
STEP 1 : Authorization Request  †
認可リクエスト
STEP 2 : Authorization Response  †
認可応答
STEP 3 : ID Token Verification  †
ID トークンの検証
STEP 4 : Accessing to UserInfo? Endpoint  †
ユーザー情報エンドポイントへのアクセス
参考  †
- デジタル・アイデンティティ技術最新動向(4):「OpenID Connect」を理解する - @IT
 
OpenID Foundation  †
IdM実験室  †
WIF  †
WIF Extension for OAuthは古い?
OWIN  †
Microsoft.Owin.Security.OpenIdConnect?
ADFS  †
Tsmatz  †
上記のコンテンツの内容を確認すると、
- Microsoft の組織アカウント (Azure Active Directory, Azure AD) と
 
- 個人アカウント (Microsoft Account, MSA) の
 
双方に対応した v2.0 endpoint (App Model v2) と連携し、
OAuth 2.0(ではなく、OpenID Connect)認証をおこない、
認証結果を他の API (Service) で検証し認証させている。
OpenId? Connectのサンプル  †
Microsoft.Owin.Security.OpenIdConnect?  †
AzureADに対して、OpenId? Connectを使用して認証する。
https://github.com/OpenTouryoProject/SampleProgram/tree/master/ASPNET/OpenID_Connect/
サンプル・アプリケーションをAzure Active Directoryに登録  †
- Azureの管理ポータルにサインイン。
 
- Azure Active Directoryのタブを開く。
 
- サンプル・アプリケーションを登録するテナント(ドメイン)を開く。
 
- [Applications]タブに移動し、ページの下部の[Add]アイコンををクリック。
 
- [What do you want to do?]画面で[Add an application my organization is developing]を選択。
 
- [Tell us about your application]画面が表示される。
- アプリケーションの名前を入力(例:OpenIDConnect_sample)。
 
- [Web Application and / or Web API]を選択する。
 
- [Next]をクリックする。
 
 
- [App properties]画面が表示される。
- サンプルのサインオンURLを入力(例:https://localhost:xxxxxx/)
サンプル・プロジェクトのプロパティにある開発サーバのSSL URLプロパティを指定
http://www.codeproject.com/Tips/766918/Visual-Studio-Use-HTTPS-SSL-On-Web-Application-Pro 
- アプリのID URIを入力(例:https://<your_tenant_name>/OpenIDConnect_sample)
'<your_tenant_name>はAzure ADのテナント(ドメイン)名。 
- [Complete]をクリック。
 
 
サンプル・アプリケーションの構成  †
- web.configファイルを開く。
 
- FxTenant?にAzure ADのテナント(ドメイン)名を指定(例:xxxxx.onmicrosoft.com)
 
- FxClientId? にAzureのポータルから入手することができるClient IDを指定
- クライアントIDを取得するには、
 
- Azureの管理ポータルにサインイン。
 
- Azure Active Directoryのタブを開く。
 
- サンプル・アプリケーションを登録したテナント(ドメイン)を開く。
 
- [Applications]タブに移動しサンプル・アプリケーションを選択。
 
- アプリケーション画面で[ACCESS WEB APIS IN OTHER APPLICATIONS]を選択。
 
- Client IDをコピー。
 
 
- FxPostLogoutRedirectUri?にサンプルのサインオンURLを入力(例:https://localhost:xxxxxx/)
 
サンプル・アプリケーションの構成  †
F5実行でリダイレクトされた先のAzure AD(STS)で認証できることを確認する。
Tags: :認証基盤, :クレームベース認証