# (OpenID Connect Core 1.0) 3 Authentication - 3.1. Authentication using the Authorization Code Flow
###### tags: `oauth2/oidc`
担当::@hijiki51:
[toc maxlevel=5]
OIDC は End-User をログインさせる、もしくはすでにログイン済みであることを確認するために 認証を行う。その結果は Client にセキュアな方法で返却されるため、Client はその結果を信頼(rely)することができる。このような理由から、OIDC Client は RP(**Relying** Party)呼ばれる。
認証フローには三つの種類が存在する。
- Authorization Code Flow
- Implicit Flow
- Hybrid Flow
それぞれ、IDToken, Access token がどのように返されるかなど、違いが存在する。
特徴表を下記に示す。
| 特徴 | Authorization Code Flow | Implicit Flow | Hybrid Flow |
|:---------------------------------- | ----------------------- |:---------------------- |:---------------------------------- |
| IDToken がどこから返却されるか | Token Endpoint | Authz Endpoint | Authz または Token Endpoint |
| AccessToken がどこから返却されるか | Token Endpoint | Authz Endpoint | Authz または Token Endpoint |
| TokenがUser Agentにわたるか | no | yes | yes |
| Client 認証が可能である | yes | no | yes |
各`response_type`とフローの組み合わせは以下のようになっている
| `response_type` | Flow |
|:------------------- |:----------------------- |
| code | Authorization Code Flow |
| id_token | Implicit Flow |
| id_token token | Implicit Flow |
| code id_token | Hybrid Flow |
| code token | Hybrid Flow |
| code id_token token | Hybrid Flow |
`code`はOAuth 2.0 で定められたものと同一である。また、OAuth 2.0 で Implicit Flowのために`token`を`response_type`として定めているが、OIDCではIDTokenを返す必要があるためこれを用いない。
### 3.1. Authentication using the Authorization Code Flow
Authorization Code Flow は Authorization Code を Client に返却し、Client はそれを用いて、Access Token&ID Tokenを Token endpointから取得する。
Token Endpoint から取得することにより、すべての Token を User Agent にさらさなくてもよくなり、悪意のあるアプリケーションから保護できる。
#### 3.1.1. Authorization Code Flow Steps
```mermaid
sequenceDiagram
participant U as User
participant C as Client
participant A as Authorization Server
C ->> A: Authorization Request w/param
Note over U,A: Authentication and get a consent
A ->> C: Redirect w/Authorization code
C ->> A: Request access token w/Authorization code
A ->> C: Response w/ID Token & Access Token
C ->> C: Validate
```
#### 3.1.2. Authorization Endpoint
- TLS を用いる必要がある(**MUST**)
##### 3.1.2.1 Authentication Request
Authentication Requeset は Authorization Server に認証を要求するための OAuth 2.0 Authorizaiton Request である。
OIDC は Authorization Request のうち、以下のパラメータを用いる。
- `scope`
- **REQUIRED**
- `openid` を含む必要がある(**MUST**)
- 解釈できない scope の値は無視するべきである(**SHOULD**)
- `response_type`
- **REQUIRED**
- OAuth 2.0 Response Type
- `client_id`
- **REQUIRED**
- OAuth 2.0 Client Identifier
- `redirect_uri`
- **REQUIRED**
- 事前に登録した Redirect URIのいずれかと完全一致する必要がある(**MUST**)
- HTTPSスキームを用いるべきである(**SHOULD**)
- Confidential Client ならば、HTTPを用いてもよい(**MAY**)
- そのほかのスキームも利用してもよい(**MAY**)
- for Native Application
- `state`
- **RECOMMENDED**
そのほかに、[OAuth 2.0 Multiple Response Type Encoding Practices](https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html)で定められた次のパラメータを用いる。
- `response_mode`
- OPTIONAL
- Authorization Response の パラメータをどこに含めうるか
- `fragment`
- 基本こっち
- `query`
- `response_type`が`none`, `code`もしくは`id_token`の時のみ
- それ以外の組み合わせの時は使ってはいけない(**MUST NOT**)
- この値は通常デフォルトの値を用いることが推奨され、リクエストで変更するべきではない(**NOT RECOMMENDED**)
OIDC は以下に示すパラメータを拡張として定義する。
- `nonce`
- OPTIONAL
- replay attack 対策のために用いる。
- 攻撃者が推測できないように十分なエントロピーを確保するべきである(**MUST**)
- `display`
- OPTIONAL
- Authentication Page をどのように表示するかを指す
- `page`
- デフォルトだとこれ
- 画面全体に認証画面が表示される
- `popup`
- 新しいWindowとしてpopup表示される
- `touch`
- 接触インターフェースを活用した形で表示される
- 指紋認証的な?
- `wap`
- フィーチャーフォン形式のUIで表示される?
- :ha:
- **W**ireless **A**pplication **P**rotocol
- https://www.docomo.ne.jp/corporate/technology/rd/technical_journal/bn/vol10_2/065.html
- https://www.wapforum.org/what/technical.htm
- そのほかの形式も許可される(**MAY**)
- `prompt`
- OPTIONAL
- 空白文字で区切られている。
- 再認証・認可を強制するかどうかを指す
- `none`
- Authorization Serverは認証・同意画面を表示してはならない(**MUST NOT**)
- 認証・認可されていなかった場合はエラーを返す(**MUST**)
- 通常は`login_required`もしくは`interaction_required`が返される
- `login`
- Authorization Server は再認証をかけるべきである(**SHOULD**)
- 認証できなかった場合はエラーを返す (**MUST**)
- 通常は`login_required`
- `consent`
- Authorization Server は同意画面をユーザーに提示するべきである(**SHOULD**)
- 同意が得られなかった場合はエラーを返す (**MUST**)
- 通常は`consent_required`
- `select_account`
- Authorization Server はユーザー選択画面を提供するべきである。(**SHOULD**)
- ユーザーが選択されなかった場合はエラーを返すべきである。(**MUST**)
- 通常は`account_selection_required`
- `none`とほかのpromptが一緒に送られた場合、エラーとなる
- `max_age`
- OPTIONAL
- 最後に認証した日時から状態の保持が許される期間
- これを超えた場合、Authorization Server は再認証を行う必要がある(**MUST**)
- この値が指定された場合、ID Tokenに`auth_time`を含まなければならない(**MUST**)
- `ui_locale`
- OPTIONAL
- 言語指定
- 解釈できなくてもエラーを返すべきでない(**SHOULD NOT**)
- `id_token_hint`
- OPTIONAL
- Authorization Server が 過去に発行した ID Tokenが入る
- ID Tokenに紐づいているユーザーがログインしている場合、正常系のレスポンスが返される
- ログインしていない場合は、エラーを返すべきである(**SHOULD**)
- `login_required`
- 可能であれば、`prompt=none`の場合には`id_token_hint`を渡すべきである(**SHOULD**)
- 渡されなければ、エラーを返してもよい(**MAY**)
- `invalid_grant`
- OPから受け取ったID Tokenが暗号化されていたならば、Clientは一度復号するべきである。(**MUST**)
- そのうえで、その中にある署名付きID Tokenを用いるべきである
- ID Tokenは再暗号化してもよい(**MAY**)
- `login_hint`
- OPTIONAL
- Authorization Server が login のために用いる識別子
- 電話番号やメールアドレスなど
- RPが事前に知っており、それを用いて認証を行う場合に用いる
- `acr_values`
- OPTIONAL
- Authentication Context Class Reference の 要求
- すなわち、どのような・どのレベルの認証を要求するかを意味する
- 満たしていれば、ID Tokenの`acr`に値が入る
##### 3.1.2.2 Authentication Request Validation
Authentication Server は以下の手順でリクエストを検証しなければならない(**MUST**)
1. Authorization Sever は すべてのOAuth 2.0 のパラメータをOAuth 2.0 の仕様に従って検証する(**MUST**)
2. `scope` に `openid` が入っていることを確認する。
- これがない場合、リクエストは単なるOAuth 2.0 のリクエストとして解釈される
1. OIDC の仕様に示されているすべての **REQUIRED** なパラメータが存在していることを検証する(**MUST**)
2. ID Tokenに対して`sub`の指定があった場合は同一の`sub`を持つID Token のみしか返してはならない。
- このような要求は主に`id_token_hint`を用いて行われる。
##### 3.1.2.3 Authorization Server Authenticates End-User
Authorization Server は以下の場合において、End-User を認証しなければならない(**MUST**)
- End-User が未認証の場合
- Authentication Request が`prompt=login`を含む場合
- この場合、すでに認証されていても再度認証を強制しなければならない
Authorization Server は以下の場合において、End-Userを**認証してはならない** (**MUST NOT**)
- Authentication Request が`prompt=none`を含む場合
- 未認証の場合はエラーを返す
##### 3.1.2.4 Authorization Server Obtains End-User Consent/Authorization
End-Userが認証されたとき、Authorization Server は RP に情報を返却する前にその情報を渡していいか認可を取らなければならない(**MUST**)
##### 3.1.2.5 Successful Authentication Response
OAuth 2.0 の Authorization Code Flow と同じ。
##### 3.1.2.6 Authentication Error Response
形式はOAuth 2.0 のAuthorization Error と同じ
OAuth 2.0 に加え、以下のエラーコードが定義される。
- `interaction_required`
- End-User が何らかの操作をする必要があるときに返却される。
- `prompt=none`の時に未認証の場合など
- `login_required`
- End-User が認証をする必要があるときに返却される。
- `prompt=none`の時に未認証の場合など
- `consent_required`
- End-Userの同意が必要な場合に返却される
- `invalid_request_uri`
- Authorization Request の`request_uri`が不正であるときに返却される
- `invalid_request_object`
- Authorization Request の`request`が不正であるときに返却される
- `request_not_supported`
- `request` パラメータに対応していないときに返却される
- 詳細は6章で話すが、`request`パラメータにJWTを含めて署名付きのリクエストを投げることができる
- `request_uri_not_supported`
- `request_uri` パラメータに対応していないときに返却される
- `registration_not_supported`
- `registration`パラメータに対応してないときに返却される
##### 3.1.2.7 Authentication Response Validation
OAuth 2.0 と同じ
#### 3.1.3 Token Endpoint
TLSの使用が必須(**MUST**)
##### 3.1.3.1 Token Request
- Confidential Clientなら Client認証を挟む必要がある
- それ以外はOAuth 2.0 と同じ
##### 3.1.3.2 Token Request Validation
Authorization Server は以下に示す手順に従って、検証をする必要がある
1. Client認証を行う
2. Authorization Code がそのクライアントに向かって発行されたものかどうか検証する
3. Authorization Code が有効かどうか検証する
4. 可能であれば、すでに Authorization Code が使われていないことを検証する
5. `redirect_uri` parameterがすでに登録されている場合、それと一致するか検証する
6. Authorization Code が Authentication Requestのレスポンスとして発行されたことを確認する
- ID Tokenを返すためには認証がすでにされている必要があるため
- Authorization Code は OAuth2.0のフローに乗って、認証なしでも発行しえる
##### 3.1.3.3 Successful Token Response
OAuth 2.0のレスポンスに加え、次のパラメータを含む(**MUST**)
- `id_token`
Token Responseには次に示すHTTP Header を含める必要がある(**MUST**)
| Header | Value |
| ------------- |:-------- |
| Cache-Control | no-store |
| Pragma | no-cache |
##### 3.1.3.4 Token Error Response
OAuth 2.0 と同じ
##### 3.1.3.5 Token Response Validation
- RFC 6749 に従って検証する
- ID Tokenの検証ルールに従う
- 3.1.3.7 目
- Access Tokenの検証ルールに従う
- 3.1.3.8 目
##### 3.1.3.6 ID Token
Authorization Code Flow では、通常のID Token に加え、以下のクレームを用いてもよい。
- `at_hash`
- Access Tokenのハッシュ値(byte)のうち、**左半分**をbase64encodeしてASCII文字列で表現したもの。
- ハッシュアルゴリズムは、ID Token のJOSE Headerにあるものと同一。
##### 3.1.3.7 ID Token Validation
1. ID Tokenが暗号化されている(JWE)ならば、復号化する。
- OP に登録するときに暗号化が約束されているならば、暗号化されていないID Token が送られてきたとき、RPはそれを拒否するべきである(**SHOULD**)
1. OPのIssuer IdentifierがID Token の`iss` Claimと一致することを確かめる(**MUST**)
2. Client IDが`aud`の値に含まれていることを確認する(**MUST**)
- 含まれていない場合は、RPはそのID Tokenを拒否しなければならない(**MUST**)
1. ID tokenが複数の`aud`を含む場合、`azp`Claimの存在を確認するべきである(**SHOULD**)
2. また、`azp`がClient ID と一致することを確認するべきである。
3. Token Endpointとの間でTLSの検証を行う(**MAY**)
4. ID Token(JWS)の検証を行う。(**MUST**)
- 検証に必要な鍵は Issuer が提供する必要がある(**MUST**)
1. ID Token の`alg`値はデフォルトで`RS256`であるべきである(**SHOULD**)
- そのほかのアルゴリズムは`id_token_signed_response_alg`を登録時に用いることで指定可能である。
1. `alg`がMAC ベースのアルゴリズムであった場合(`HS256`など)は、`aud`に含まれるClient ID に対応する Client Secretが検証に用いられる。
- `aud`が複数の時の動作及び、`aud`と異なる`azp`があるときの動作は未定義である。
1. 現在時刻が`exp`の前であることを確認する(**MUST**)
2. `iat`を用いて現在時刻よりもはるかに昔に発行されたトークンを拒否することができる。
3. nonceがAuthentication Request で送られたならば、`nonce` Claimが存在し、それが一致することを確認する(**MUST**)
4. `acr` Claim が要求したなら、Clientは発行された`acr`の値が適切かどうか確認するべきである(**SHOULD**)
6. `auth_time` Claimが発光されたなら、 Client はその値を検証し、認証時刻から長い時間が流れたと判断した場合は、再認証を要求するべきである(**SHOULD**)
##### 3.1.3.8 Access Token Validation
Implicit Flow と同様に、`at_hash`を用いて、Access Token を検証する必要がある。(**MUST**)