登場するもの
OAuthにおけるロール
| Role | 役割 |
| Resource Owner | リソースの所有者。通常はユーザ。 |
| Client | Resource Ownerの代わりにリソースへアクセスするアプリケーション。 |
| Authorization Server | 認可コードやアクセストークンを発行するサーバー。 |
| Resource Server | アクセストークンを受け取り、保護されたリソースを提供するサーバー。 |
このほかに、実際の認可コードフローでは、ブラウザ(User-Agent)がClientとAuthorization Server間のリダイレクトを仲介する。
(RFCとしてはブラウザは出てこない)
Client Secret
Client Secretは「どのClientなのか」を認証する仕組み。ClientSecretは共通だが、PKCEのcode_verifierは認可処理ごとに生成する。
PKCE(ピクシー/Proof Key for Code Exchange)
OAuth 2.0の認可コードフローにおいて、Authorization Code(認可コード)を第三者に盗まれても、Access Tokenへの交換を防ぐための仕組み。
PCKEでは、Clientが2つの値を使用する。
code_verifier:Clientが生成する推測困難なランダム文字列
code_challenge :code_verifier から計算した値
Public Clientでは、PKCEの使用が必須とされており、Confidential Clientでも利用を推奨されている。
Confidential Client:Clientの認証情報を安全に保持できるクライアント(サーバサイドWebアプリ)
Public Client:Clientの認証情報を安全に保持できないクライアント(SPA、スマートフォンアプリ、デスクトップアプリ)
簡易認可コードフロー
sequenceDiagram
actor RO as Resource Owner<br/>ユーザー
participant B as Browser<br/>※OAuthのRoleではない
participant C as Client
participant AS as Authorization Server
participant RS as Resource Server
RO->>B: ① 外部サービスとの連携を開始
B->>C: ② 連携開始
Note over B,AS: フロントチャネル
C-->>B: ③ Authorization Serverへ誘導
B->>AS: ④ 認可リクエスト
AS-->>B: ⑤ 認証・認可
B->>AS: ⑥ アクセスを許可
AS-->>B: ⑦ Authorization Codeを付けてClientへ誘導
B->>C: ⑧ Authorization Code
Note over C,AS: バックチャネル
C->>AS: ⑨ Authorization Codeを<br/>Access Tokenに交換
AS-->>C: ⑩ Access Token
C->>RS: ⑪ Access TokenでAPIアクセス
RS-->>C: ⑫ リソースフロントチャネルとは、ブラウザを経由する通信です。
バックチャネルとは、ClientとAuthorization Serverが直接行う通信です。
詳細な認可コードフロー
sequenceDiagram
actor RO as Resource Owner<br/>ユーザー
participant B as Browser<br/>※OAuthのRoleではない
participant C as Client
participant AS as Authorization Server
participant RS as Resource Server
%% OAuth開始
RO->>B: ① 「外部サービスと連携」を選択
B->>C: ② 連携開始リクエスト
%% Client側の準備
C->>C: ③ state生成<br/>code_verifier生成<br/>code_challenge生成
%% Front Channel
rect rgb(240, 245, 255)
Note over B,AS: フロントチャネル(User-Agentを経由)
C-->>B: ④ Authorization Endpointへ<br/>302 Redirect
B->>AS: ⑤ Authorization Request<br/>GET /authorize<br/>response_type=code<br/>client_id<br/>redirect_uri<br/>scope<br/>state<br/>code_challenge<br/>code_challenge_method=S256
AS-->>B: ⑥ 認証・認可画面
RO->>B: ⑦ 認証情報入力・アクセス許可
B->>AS: ⑧ 認証・認可に必要な情報を送信
AS-->>B: ⑨ Clientへ302 Redirect<br/>code + state
B->>C: ⑩ Redirect URIへアクセス<br/>GET /callback<br/>code + state
end
%% Back Channel
rect rgb(245, 255, 245)
Note over C,AS: バックチャネル(User-Agentを経由しない)
C->>AS: ⑪ Token Request<br/>POST /token<br/>grant_type=authorization_code<br/>code<br/>code_verifier
AS->>AS: ⑫ Authorization Code検証<br/>PKCE検証
AS-->>C: ⑬ Token Response<br/>Access Token
end
%% Resource Access
rect rgb(255, 250, 240)
Note over C,RS: Resource ServerへのAPIアクセス
C->>RS: ⑭ Resource Request<br/>Authorization: Bearer Access Token
RS-->>C: ⑮ Resource Response<br/>Protected Resource
end②Browser → Client:連携開始リクエスト
連携開始リクエストです。ユーザが「外部サービスとの連携」などのボタンをクリックしたら、例えばClientが app.example.com だった場合、以下のような表示が行われます。
<a href="/oauth/start">外部サービスと連携</a>
GET /oauth/start HTTP/1.1
Host: app.example.com
Cookie: session=...
上記のようなリクエストが送られます。
③Client:認可リクエストの準備
②を受け取ったClientは、Authorization Serverへユーザーを誘導する準備をします。
PKCEを使用する今回の例では、[ state / code_verifier / code_challenge ] を生成しています。
state : Clientが認可リクエストと、そのあとに返ってくるレスポンスを関連付けるために使用する値です。認可リクエストとコールバックを関連づける値でもある。
code_verifier : PCKEのためにClientが生成するランダムな値。この時点ではAuthorizationServerには送らず、Client側で保持しておく。11のToken Requestで初めてAuthorizationServerへ送る。
code_challenge : code_verifierから生成する値。BASE64URL(SHA256(code_verifier))という関係性。
④ Client → Browser:Authorization Endpointへ302 Redirect
③で準備した値を使って、BrowserをAuthorization Serverへ誘導します。
HTTP/1.1 302 Found
Location: https://auth.example.com/authorize?
response_type=code&
client_id=client123&
redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback&
scope=profile&
state=xyz123&
code_challenge=xxxxx&
code_challenge_method=S256
⑤ Browser → Authorization Server:Authorization Request
④の Location を受け取ったBrowserが、Authorization Serverへアクセスします。
GET /authorize?
response_type=code&
client_id=client123&
redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback&
scope=profile&
state=xyz123&
code_challenge=xxxxx&
code_challenge_method=S256 HTTP/1.1
Host: auth.example.com
| パラメータ | 意味 |
response_type=code | Authorization Codeを要求 |
client_id | Clientの識別子 |
redirect_uri | 認可後の戻り先 |
scope | Clientが要求する権限 |
state | リクエストとレスポンスの関連付け等 |
code_challenge | PKCEで使用 |
code_challenge_method=S256 | SHA-256を使用 |
ここからはAuthorizationServer側の処理になる。
⑥ Authorization Server → Browser:認証・認可画面
Authorization Serverは、必要に応じてユーザにログインや認可画面を表示します。
例えば、
PhotoEditorがあなたの写真データへのアクセスを要求しています。
「許可」「キャンセル」
という画面です。
⑦ Resource Owner → Browser:認証・アクセス許可
ユーザーがBrowser上で、ID/パスワードを入力し、「許可」をクリックします。
(人間による操作なので、Resource OwnerからAuthorization Serverへ直接HTTP通信しているわけではありません。)
⑧ Browser → Authorization Server:認証・認可情報の送信
Browserがユーザーの操作結果をAuthorization Serverへ送信します。
概念的には、
POST /... HTTP/1.1
Host: auth.example.com
...
のような通信です。このHTTPリクエストはOAuthが標準化したものではありません。ログイン画面やMFA、同意画面の実装はAuthorizationServerによって異なるためです。
⑨ Authorization Server → Browser:Authorization Codeを付けてRedirect
ユーザーによる認可が完了すると、Authorization ServerはAuthorization Codeを発行します。
そしてBrowserに対してClientへ戻るよう指示します。
HTTP/1.1 302 Found
Location: https://client.example.com/callback?
code=ABC123&
state=xyz123
あくまでAuthorizationServerがBrowserに必要なデータを渡し、Clientへ行きなさいと指示しているだけです。
⑩ Browser → Client:Redirect URIへアクセス
Browserが⑨のリダイレクトに従います。
GET /callback?code=ABC123&state=xyz123 HTTP/1.1
Host: client.example.com
これによって、Clientが
Authorization Code = ABC123
state = xyz123
を受け取ります。
Clientはここで返されたstateが、自分が⑤で送ったものと対応しているか確認します。
ここまでがフロントチャネルです。
⑪ Client → Authorization Server:Token Request
ここから大きく通信経路が変わります。
Browserを経由せず、ClientがAuthorization ServerのToken Endpointへリクエストします。
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=ABC123&
redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback&
client_id=client123&
code_verifier=yyyyyyyy
③で生成して保持していたcode_verifier がここで登場します。
⑫ Authorization Server:Authorization Code・PKCE等を検証
Authorization ServerはToken Requestを検証します。
PKCEについては概念的に、⑪で受信したcode_verifierから算出した値と⑤で受け取っていたcode_verifierを比較します。
Authorization Codeだけを持ってきても、正しい code_verifier を提示できなければTokenを取得できません。
Authorization CodeそのものやClient、Redirect URIなど、Authorization Code Grantとして必要な検証も行われます。
⑬ Authorization Server → Client:Token Response
検証に成功すると、Access Tokenが発行されます。
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
{
"access_token": "TOKEN123",
"token_type": "Bearer",
"expires_in": 3600
}
構成によってはRefresh Tokenなども返されます。
⑭ Client → Resource Server:Access TokenでAPIアクセス
Clientは取得したAccess Tokenを使ってResource Serverへアクセスします。
例えば、以下のかたちです。
GET /api/photos HTTP/1.1
Host: api.example.com
Authorization: Bearer TOKEN123
Resource ServerはAccess Tokenを確認して、要求されたリソースへのアクセスを許可するか判断します。
ここで初めて、OAuthを使ってClientが取得した権限が実際のAPIアクセスに使われます。
⑮ Resource Server → Client:Protected Resourceを返す
Access Tokenが有効で、必要な権限を持っていればResource Serverがリソースを返します。
HTTP/1.1 200 OK
Content-Type: application/json
{
"photos": [...]
}
これで一連の流れが完了します。