Edited at

OpenID Connect 全フロー解説


はじめに

OpenID ConnectOAuth 2.0 を拡張する形で策定されました。

OAuth 2.0 はアクセストークン発行手順に関する仕様で、RFC 6749(The OAuth 2.0 Authorization Framework)で定義されています(参考:一番分かりやすい OAuth の説明)。

一方、OpenID Connect は ID トークン発行手順に関する仕様で、主要部分は OpenID Connect Core 1.0 で定義されています(参考:一番分かりやすい OpenID Connect の説明)。

RFC 6749 は認可エンドポイントという Web API を定義しています。 この API は必須のリクエストパラメーターとして response_type を要求します。 OpenID Connect は、この response_type の仕様を拡張することにより ID トークン発行手順を定義しました。

RFC 6749 の時点では response_type が取りうる値は codetoken のどちらかでしたが、OpenID Connect では、id_token という新しい値を追加した上で、codetokenid_token の任意の組み合わせresponse_type に指定してもよいことにしました。 加えて、none という特殊な値も定義しました。 この結果、response_type は次の値を取りうることになりました。

response_type

1
code

2
token

3
id_token

4
id_token token

5
code id_token

6
code token

7
code id_token token

8
none

以降、response_type の値ごとにフローを紹介します。

なお、ID トークンの発行を要求するリクエストは、scope リクエストパラメーターに openid という値を含める必要があります。 特に、scopeopenid を含めていないと、response_type=code のケースは RFC 6749 の認可コードフローそのものとして扱われ、ID トークンは発行されないので注意してください。 response_type=code token についても同様のことが言えます。


1. response_type=code

response_type の値が code の場合、これだけでは RFC 6749 の認可コードフローと何も変わりません。 しかし、scopeopenid が含まれている場合、トークンエンドポイントから、アクセストークンに加えて ID トークンも発行されます。

scopeopenid が含まれる場合

認可コード
アクセストークン
ID トークン

認可エンドポイント
発行

トークンエンドポイント

発行
発行

code+openid.png

scopeopenid が含まれない場合(RFC 6749 の認可コードフロー

認可コード
アクセストークン
ID トークン

認可エンドポイント
発行

トークンエンドポイント

発行

code-openid.png


2. response_type=token

response_type の値が token の場合、これは RFC 6749 のインプリシットフローそのものです。 scopeopenid が含まれていたとしても ID トークンは発行されません。

認可コード
アクセストークン
ID トークン

認可エンドポイント

発行

token.png

OpenID Connect では token という応答タイプを使わないことは、OpenID Connect Core 1.0 の「3. Authentication」の末尾に明示的に書かれています。


NOTE: While OAuth 2.0 also defines the token Response Type value for the Implicit Flow, OpenID Connect does not use this Response Type, since no ID Token would be returned.



3. response_type=id_token

response_typeid_token の場合、認可エンドポイントから ID トークンが発行されます。 このフローではトークンエンドポイントは使われません。

認可コード
アクセストークン
ID トークン

認可エンドポイント


発行

id_token.png


4. response_type=id_token token

response_typeid_token token の場合、認可エンドポイントからアクセストークンと ID トークンが発行されます。 このフローではトークンエンドポイントは使われません。

認可コード
アクセストークン
ID トークン

認可エンドポイント

発行
発行

id_token_token.png

認可エンドポイントから ID トークンと共にアクセストークンを発行する場合、ある方法で計算されたアクセストークンのハッシュ値を ID トークンに埋め込む必要があるので、このフローを実装する際は注意してください。 OpenID Connect Core 1.0 の「3.2.2.10. ID Token」には次のように書かれています。


at_hash

Access Token hash value. Its value is the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of the access_token value, where the hash algorithm used is the hash algorithm used in the alg Header Parameter of the ID Token's JOSE Header. For instance, if the alg is RS256, hash the access_token value with SHA-256, then take the left-most 128 bits and base64url encode them. The at_hash value is a case sensitive string.

If the ID Token is issued from the Authorization Endpoint with an access_token value, which is the case for the response_type value id_token token, this is REQUIRED; it MAY NOT be used when no Access Token is issued, which is the case for the response_type value id_token.



5. response_type=code id_token

response_typecode id_token の場合、認可エンドポイントから認可コードと ID トークンが、トークンエンドポイントからアクセストークンと ID トークンが発行されます。

認可コード
アクセストークン
ID トークン

認可エンドポイント
発行

発行

トークンエンドポイント

発行
発行

code_id_token.png

認可エンドポイントとトークンエンドポイントの両方から ID トークンが発行されますが、双方の ID トークンの内容は必ずしも同じとは限りません。 これについて OpenID Connect Core 1.0 の「3.3.3.6 ID Token」で次のように述べられています。


If an ID Token is returned from both the Authorization Endpoint and from the Token Endpoint, which is the case for the response_type values code id_token and code id_token token, the iss and sub Claim Values MUST be identical in both ID Tokens. All Claims about the Authentication event present in either SHOULD be present in both. If either ID Token contains Claims about the End-User, any that are present in both SHOULD have the same values in both. Note that the OP MAY choose to return fewer Claims about the End-User from the Authorization Endpoint, for instance, for privacy reasons. The at_hash and c_hash Claims MAY be omitted from the ID Token returned from the Token Endpoint even when these Claims are present in the ID Token returned from the Authorization Endpoint, because the ID Token and Access Token values returned from the Token Endpoint are already cryptographically bound together by the TLS encryption performed by the Token Endpoint.


認可エンドポイントから ID トークンと共に認可コードを発行する場合、ある方法で計算された認可コードのハッシュ値を ID トークンに埋め込む必要があるので、このフローを実装する際は注意してください。 OpenID Connect Core 1.0 の「3.3.2.11. ID Token」には次のように書かれています。


c_hash

Code hash value. Its value is the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of the code value, where the hash algorithm used is the hash algorithm used in the alg Header Parameter of the ID Token's JOSE Header. For instance, if the alg is HS512, hash the code value with SHA-512, then take the left-most 256 bits and base64url encode them. The c_hash value is a case sensitive string.

If the ID Token is issued from the Authorization Endpoint with a code, which is the case for the response_type values code id_token and code id_token token, this is REQUIRED; otherwise, its inclusion is OPTIONAL.



6. response_type=code token

response_typecode token の場合、認可エンドポイントから認可コードとアクセストークンが発行され、トークエンドポイントからアクセストークンが発行されます。 加えて、scopeopenid が含まれる場合は、トークンエンドポイントから ID トークンも発行されます。

scopeopenid が含まれる場合

認可コード
アクセストークン
ID トークン

認可エンドポイント
発行
発行

トークンエンドポイント

発行
発行

code_token+openid.png

scopeopenid が含まれない場合

認可コード
アクセストークン
ID トークン

認可エンドポイント
発行
発行

トークンエンドポイント

発行

code_token-openid.png

認可エンドポイントとトークンエンドポイントの両方からアクセストークンが発行されますが、双方のアクセストークンは必ずしも同じとは限りません。 これについて OpenID Connect Core 1.0 の「3.3.3.8. Access Token」に次のように書かれています。


If an Access Token is returned from both the Authorization Endpoint and from the Token Endpoint, which is the case for the response_type values code token and code id_token token, their values MAY be the same or they MAY be different. Note that different Access Tokens might be returned be due to the different security characteristics of the two endpoints and the lifetimes and the access to resources granted by them might also be different.



7. response_type=code id_token token

response_typecode id_token token の場合、認可エンドポイントから認可コード、アクセストークン、ID トークンが発行され、トークエンドポイントからアクセストークンと ID トークンが発行されます。

認可コード
アクセストークン
ID トークン

認可エンドポイント
発行
発行
発行

トークンエンドポイント

発行
発行

code_id_token_token.png

認可エンドポイントとトークンエンドポイントの両方からアクセストークンが発行されますが、双方のアクセストークンは必ずしも同じとは限りません。 これは「6. response_type=code token」と同様です。 仕様については OpenID Connect Core 1.0 の「3.3.3.8. Access Token」を参照してください。

認可エンドポイントから ID トークンを発行する際、アクセストークンも共に発行する場合は当該アクセストークンのハッシュ値を、認可コードも共に発行する場合は当該認可コードのハッシュ値を、ID トークンに埋め込む必要があります。 これは「4. response_type=id_token token」や「5. response_type=code id_token」と同様です。 仕様については OpenID Connect Core 1.0 の「3.3.2.11. ID Token」を参照してください。


8. response_type=none

response_typenone の場合、認可エンドポイントからは何も発行されません。 このフローではトークンエンドポイントは使われません。

認可コード
アクセストークン
ID トークン

認可エンドポイント


none.png

none の定義自体は OAuth 2.0 Multiple Response Type Encoding Practices の「4. None Response Type」にあります。


9. サポート状況

OpenID Connect サポートを謳っているソフトウェアが上記全てのフローをサポートしているとは限りません。 OpenID Certification 取得済みの OpenID プロバイダーの実装に限っても、約半数は Hybrid OP プロファイルを取得していないので(=ハイブリッドフローをサポートしていないので)、全フローをサポートしている OpenID プロバイダーの実装はむしろ少数派と考えてよいでしょう。

OpenID FoundationFinancial API ワーキンググループが仕様策定中の Financial API では、更新系 API を利用するためのアクセストークンを取得するためには、response_type の値を code id_token もしくは code id_token token として認可リクエストを投げなければなりません。 Financial Services – Financial API - Part 2: Read and Write API Security Profile の「5.2.2. Authorization Server」)には次のように書かれています。


shall require the response_type values code id_token or code id_token token;


これはつまり、Financial API への準拠を考えているのであれば、OpenID Connect のハイブリッドフローをサポートしている認可サーバーを使用する必要があるということです。 世の中には response_type=code しかサポートしていない OpenID Connect 実装も実在するので、認可サーバー選択の際は注意してください。

追記:2019 年 4 月 20 日

2018 年 10 月に承認された FAPI 第二版では、JARM を使う場合、ID トークンを Detached Signature として用いる必要がなくなるため、更新系 API 用アクセストークンを要求する場合でも、response_typeid_token を含めなくてもよくなります。詳細は『【2019年版】世界最先端の API セキュリティー技術、実装者による『FAPI(Financial-grade API)』解説』の『2.5. Part 2: JARM』を参照してください。


おわりに

こんな複雑なもの実装していられない、と思った方は Authlete(オースリート)の利用をご検討ください!(参考:OAuth 2.0 / OIDC 実装の新アーキテクチャー