OAuth

OAuth 2.0 全フローの図解と動画

More than 1 year has passed since last update.

RFC 6749 (The OAuth 2.0 Authorization Framework) で定義されている 4 つの認可フロー、および、リフレッシュトークンを用いてアクセストークンの再発行を受けるフローの図解及び動画です。動画は YouTube へのリンクとなっています。

English version: Diagrams And Movies Of All The OAuth 2.0 Flows


1. 認可コードフロー

RFC 6749, 4.1. Authorization Code Grant で定義されているフローです。認可エンドポイントに認可リクエストを投げ、応答として短命の認可コードを受けとり、その認可コードをトークンエンドポイントでアクセストークンと交換するフローです。

動画: OAuth 2.0, Authorization Code Flow (in Japanese)

RFC6749-4_1-authorization_code_flow-Japanese.png


1.1. 認可エンドポイントへのリクエスト

GET {認可エンドポイント}

?response_type=code // 必須
&client_id={クライアントID} // 必須
&redirect_uri={リダイレクトURI} // 条件により必須
&scope={スコープ群} // 任意
&state={任意文字列} // 推奨
&code_challenge={チャレンジ} // 任意
&code_challege_method={メソッド} // 任意
HTTP/1.1
HOST: {認可サーバー}

※:上記は、RFC 6749 に加え RFC 7636 で定義されたリクエストパラメーターも含んでいます。詳細はこちら


1.2. 認可エンドポイントからのレスポンス

HTTP/1.1 302 Found

Location: {リダイレクトURI}
?code={認可コード} // 必須
&state={任意文字列} // 認可リクエストに state が含まれていれば必須


1.3. トークンエンドポイントへのリクエスト

POST {トークンエンドポイント} HTTP/1.1

Host: {認可サーバー}
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code // 必須
&code={認可コード} // 必須 認可エンドポイントのレスポンスに含まれる値を指定
&redirect_uri={リダイレクトURI} // 認可リクエストに redirect_uri が含まれていれば必須
&code_verifier={ベリファイア} // 認可リクエストに code_challenge が含まれていれば必須

※:上記は、RFC 6749 に加え RFC 7636 で定義されたリクエストパラメーターも含んでいます。詳細はこちら

条件によってはクライアント認証を求められることがあり、その場合は Basic 認証(Authorization ヘッダー)もしくは client_id & client_secret パラメーターを追加します。


1.4. トークンエンドポイントからのレスポンス

HTTP/1.1 200 OK

Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
"access_token":"{アクセストークン}", // 必須
"token_type":"{トークンタイプ}", // 必須
"expires_in":{有効秒数}, // 任意
"refresh_token":"{リフレッシュトークン}", // 任意
"scope":"{スコープ群}" // 要求したスコープ群と差異があれば必須
}


2. インプリシットフロー

RFC 6749, 4.2. Implicit Grant で定義されているフローです。認可エンドポイントに認可リクエストを投げ、応答として直接アクセストークンを受け取るフローです。

動画: OAuth 2.0, Implicit Flow (in Japanese)

RFC6749-4_2-implicit_flow-Japanese.png


2.1. 認可エンドポイントへのリクエスト

GET {認可エンドポイント}

?response_type=token // 必須
&client_id={クライアントID} // 必須
&redirect_uri={リダイレクトURI} // 条件により必須
&scope={スコープ群} // 任意
&state={任意文字列} // 推奨
HTTP/1.1
HOST: {認可サーバー}


2.2. 認可エンドポイントからのレスポンス

HTTP/1.1 302 Found

Location: {リダイレクトURI}
#access_token={アクセストークン} // 必須
&token_type={トークンタイプ} // 必須
&expires_in={有効秒数} // 任意
&state={任意文字列} // 認可リクエストに state が含まれていれば必須
&scope={スコープ群} // 要求したスコープ群と差異があれば必須

インプリシットフローではリフレッシュトークンは発行されません。


3. リソースオーナー・パスワード・クレデンシャルズフロー

RFC 6749, 4.3. Resource Owner Password Credentials Grant で定義されているフローです。トークンエンドポイントにトークンリクエストを投げ、応答としてアクセストークンを受け取るフローです。OAuth のフローですが、クライアントアプリケーションがユーザーの ID とパスワードを受けとります。このフローについては、「OAuth 2.0 + OpenID Connect のフルスクラッチ実装者が知見を語る」の「Resource Owner Password Credentials Grant について」もご参照ください。

動画: OAuth 2.0, Resource Owner Password Credentials Flow (in Japanese)

Resource-Owner-Password-Credentials-Flow-in-Japanese.png


3.1. トークンエンドポイントへのリクエスト

POST {トークンエンドポイント} HTTP/1.1

Host: {認可サーバー}
Content-Type: application/x-www-form-urlencoded

grant_type=password // 必須
&username={ユーザーID} // 必須
&password={パスワード} // 必須
&scope={スコープ群} // 任意

条件によってはクライアント認証を求められることがあり、その場合は Basic 認証(Authorization ヘッダー)もしくは client_id & client_secret パラメーターを追加します。


3.2. トークンエンドポイントからのレスポンス

HTTP/1.1 200 OK

Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
"access_token":"{アクセストークン}", // 必須
"token_type":"{トークンタイプ}", // 必須
"expires_in":{有効秒数}, // 任意
"refresh_token":"{リフレッシュトークン}", // 任意
"scope":"{スコープ群}" // 要求したスコープ群と差異があれば必須
}


4. クライアント・クレデンシャルズフロー

RFC 6749, 4.4. Client Credentials Grant で定義されているフローです。トークンエンドポイントにトークンリクエストを投げ、応答としてアクセストークンを受け取るフローです。このフローでは、ユーザーの認証はおこなわれず、クライアントアプリケーションの認証のみがおこなわれます。

動画: OAuth 2.0, Client Credentials Flow (in Japanese)

Client-Credentials-Flow-in-Japanese.png


4.1. トークンエンドポイントへのリクエスト

POST {トークンエンドポイント} HTTP/1.1

Host: {認可サーバー}
Authorization: Basic {クライアントクレデンシャルズ}
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials // 必須
&scope={スコープ群} // 任意

クライアント・クレデンシャルズフローは、confidential クライアント (RFC 6749, 2.1. Client Types 参照) のみに許されており、結果、必ずクライアント認証が求められます。Basic 認証(Authorization ヘッダー)もしくは client_id & client_secret パラメーターが必要になります。


4.2. トークンエンドポイントからのレスポンス

HTTP/1.1 200 OK

Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
"access_token":"{アクセストークン}", // 必須
"token_type":"{トークンタイプ}", // 必須
"expires_in":{有効秒数}, // 任意
"scope":"{スコープ群}" // 要求したスコープ群と差異があれば必須
}

クライアント・クレデンシャルズフローでは、リフレッシュトークンを発行すべきではないとされています。


5. リフレッシュトークンフロー

RFC 6749, 6. Refreshing an Access Token で定義されているフローです。事前に発行を受けていたリフレッシュトークンをトークンエンドポイントに提示することにより、アクセストークンの再発行を受けます。

動画: OAuth 2.0, Refresh Token Flow (in Japanese)

Refresh-Token-Flow-in-Japanese.png


5.1. トークンエンドポイントへのリクエスト

POST {トークンエンドポイント} HTTP/1.1

Host: {認可サーバー}
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token // 必須
&refresh_token={リフレッシュトークン} // 必須
&scope={スコープ群} // 任意

条件によってはクライアント認証を求められることがあり、その場合は Basic 認証(Authorization ヘッダー)もしくは client_id & client_secret パラメーターを追加します。


5.2. トークンエンドポイントからのレスポンス

HTTP/1.1 200 OK

Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
"access_token":"{アクセストークン}", // 必須
"token_type":"{トークンタイプ}", // 必須
"expires_in":{有効秒数}, // 任意
"refresh_token":"{リフレッシュトークン}", // 任意
"scope":"{スコープ群}" // 元のスコープ群と差異があれば必須
}


まとめ

フロー
認可エンドポイント
トークンエンドポイント
特徴

認可コード
使う
使う
短命の認可コードの発行を受け、トークンエンドポイントでアクセストークンと交換する。

インプリシット
使う
使わない
認可エンドポイントから直接アクセストークンの発行を受ける。

リソースオーナー・パスワード・クレデンシャルズ
使わない
使う
ユーザーの ID とパスワードをクライアントに渡す。

クライアント・クレデンシャルズ
使わない
使う
クライアントアプリの認証のみでアクセストークンの発行を受ける。

リフレッシュトークン
使わない
使う
リフレッシュトークンを提示してアクセストークンの再発行を受ける。


おまけ

OAuth 2.0 や OpenID Connect、UMA など、数多くの標準仕様の策定に携わり、『OAuth 2 in Action』の著者としても知られる Justin Richer 氏が、2017 年 7 月 27 日に『Deployment and Hosting Patterns in OAuth』という記事を公開しました。 その記事の中で彼は、認可サーバーの実装方法を 4 つに分類し、『Semi-Hosted Service パターン』の例として Authlete(オースリート)に言及しました。 詳細は『OAuth 2.0 / OIDC 実装の新アーキテクチャー』をご参照ください。

Semi-Hosted Service パターンでは、認可機能を提供するバックエンドサービスを利用して、フロントの認可サーバーを実装します。 この実装方法のアーキテクチャーは通常の認可サーバーのそれより当然複雑になりますが、その利点は何かというと、バックエンドサービスが OAuth 2.0 と OpenID Connect の実装に専門特化できることです。 アイデンティティー管理やユーザー認証、セッション管理、API 管理、不正検出など、API まわりの他の技術要素から独立し、OAuth 2.0 と OpenID Connect の実装に集中することができます。 このアーキテクチャーから必然的に導かれるもう一つの利点は、バックエンドサービス(OAuth 2.0 と OpenID Connect の実装)を、他の技術要素のどのようなソリューションとも組み合わせることができることです。 例えば、ユーザー認証にどのような方法を用いてもよく、FIDO のような新しい認証ソリューションが登場しても、問題無く対応できます。

ここでは、おまけとして、Authlete をバックエンドサービスとして用いたときに OAuth 2.0 の各フローがどのように実装されることになるかを、図でご紹介します。 丁寧に図を見ていただくと、Authlete がどうして「どんなユーザー認証方法とも組み合わせることができる」のかが分かると思います。


認可コードフロー + Authlete

OAuth-Flows+Authlete-in-Japanese_2_Authorization-Code-Flow.png


インプリシットフロー + Authlete

OAuth-Flows+Authlete-in-Japanese_3_Implicit-Flow.png


リソースオーナー・パスワード・クレデンシャルズフロー + Authlete

OAuth-Flows+Authlete-in-Japanese_4_Resource-Owner-Password-Credentials-Flow.png


クライアント・クレデンシャルズフロー + Authlete

OAuth-Flows+Authlete-in-Japanese_5_Client-Credentials-Flow.png


リフレッシュトークンフロー + Authlete

OAuth-Flows+Authlete-in-Japanese_6_Refresh-Token-Flow.png