TL;DR
OAuth 2.0 の認可コードフローで、認可コード横取り攻撃を防ぐための拡張仕様。2015 年 9 月に RFC 7636 として標準化され、OAuth 2.1 では必須になっている。
なぜ必要か
認可コードが攻撃者に横取りされると、攻撃者はそのコードでトークンを取得できてしまう。PKCE では、クライアントが毎回ランダムな秘密値を生成するので、認可リクエストを始めたクライアントと、トークンを受け取るクライアントが同じであることを保証できる。
仕組み
クライアントは認可リクエストに code_challenge と code_challenge_method を付けて送り、トークンリクエストでは認可コードと一緒に code_verifier を送る。認可サーバは code_verifier を変換した値が code_challenge と一致するかを確かめ、一致しなければトークンを発行しない。
sequenceDiagram autonumber participant U as リソースオーナ<br/>(ユーザー / ブラウザ) participant C as クライアント participant AS as 認可サーバ U->>C: アプリにアクセス / ログイン開始 C->>U: 認可リクエストへリダイレクト<br/>(code_challenge, code_challenge_method を付与) U->>AS: 認可リクエスト<br/>+ code_challenge + code_challenge_method AS->>U: ログイン / 同意画面 U->>AS: 認証・同意 AS->>U: 認可コードを付けてリダイレクト U->>C: 認可コードを引き渡し C->>AS: トークンリクエスト<br/>+ 認可コード + code_verifier alt 一致する AS->>C: アクセストークン(+リフレッシュトークン)を発行 C->>U: ログイン完了 else 一致しない / code_verifier が無い AS->>C: エラー応答 (invalid_grant 等) — 拒否 end
パラメータ
code_verifier は、認可リクエストとトークンリクエストを紐づけるためのランダムな文字列である。長さは 43〜128 文字で、英数字と一部の記号(-、.、_、~)を使える。十分なエントロピーを確保するために、暗号論的擬似乱数生成器(CSPRNG)で生成する必要がある。
code_challenge_method は、code_verifier から code_challenge を導出するときの変換方法である。推奨は S256 で、SHA-256 でハッシュ化する。plain は変換せずにそのまま使う方法で、OAuth 2.1 では SHA-256 を実行できないクライアント以外は使うべきでないとされている。サポートしていない変換方法を要求されたときは、認可サーバは invalid_request エラーを返す必要がある。
S256: code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
plain: code_challenge = code_verifiercode_challenge は、code_verifier から導出され、認可リクエストで送られるチャレンジ値である。