PKCE
OAuth 2.0 の認可コードフローを、クライアントシークレットなしで安全に実行するための拡張
PKCE とは
PKCE (Proof Key for Code Exchange、ピクシーと読む) は、RFC 7636 で定義された OAuth 2.0 の拡張で、認可コードの横取り攻撃を防ぐ仕組みである。元々はモバイルアプリや SPA など、クライアントシークレットを安全に保持できないパブリッククライアント向けに設計されたが、OAuth 2.1 では全クライアントで PKCE が必須になった。
なぜ PKCE が必要か
通常の認可コードフローでは、認可コードを横取りした攻撃者がトークンを取得できる。
1. ユーザーが認可サーバーにログイン
2. 認可サーバーがリダイレクト URL に認可コードを付与
3. ❌ 攻撃者がリダイレクトを傍受し、認可コードを横取り
4. 攻撃者が認可コードでトークンを取得
PKCE は、認可コードとトークン交換を暗号学的に紐づけることで、横取りされた認可コードを無効化する。
PKCE のフロー
PKCE のフローを図で示す。
1. クライアントがランダムな code_verifier を生成
2. code_verifier の SHA-256 ハッシュ = code_challenge を計算
3. 認可リクエストに code_challenge を含める
4. 認可サーバーがリダイレクトで認可コードを返す
5. トークンリクエストに code_verifier を含める
6. 認可サーバーが code_verifier のハッシュと code_challenge を照合
7. 一致すればトークンを発行
攻撃者が認可コードを横取りしても、code_verifier を知らないためトークンを取得できない。
実装
実装のコード例を示す。
import { randomBytes, createHash } from 'crypto';
// 1. code_verifier を生成 (43〜128文字のランダム文字列)
const codeVerifier = randomBytes(32).toString('base64url');
// 2. code_challenge を計算
const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');
// 3. 認可リクエスト
const authUrl = new URL('https://auth.example.com/authorize');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('client_id', CLIENT_ID);
authUrl.searchParams.set('redirect_uri', REDIRECT_URI);
authUrl.searchParams.set('code_challenge', codeChallenge);
authUrl.searchParams.set('code_challenge_method', 'S256');
// 5. トークンリクエスト (認可コード + code_verifier)
const tokenResponse = await fetch('https://auth.example.com/token', {
method: 'POST',
body: new URLSearchParams({
grant_type: 'authorization_code',
code: authorizationCode,
redirect_uri: REDIRECT_URI,
client_id: CLIENT_ID,
code_verifier: codeVerifier, // ← これが PKCE の核心
}),
});
Cognito での PKCE
Cognito User Pool は PKCE をネイティブにサポートする。Hosted UI を使う場合、code_challenge と code_challenge_method をクエリパラメータに含めるだけでよい。
PKCE なしの認可コードフロー (非推奨)
PKCE なしの認可コードフロー (非推奨) を以下にまとめる。
| フロー | PKCE | クライアントシークレット | 用途 |
|---|---|---|---|
| 認可コード + PKCE | ✅ | 不要 | SPA、モバイル (推奨) |
| 認可コード + シークレット | ❌ | 必要 | サーバーサイドアプリ |
| Implicit (非推奨) | ❌ | 不要 | 廃止予定 |
Implicit フローはトークンが URL フラグメントに露出するため、OAuth 2.1 で廃止された。PKCE 付き認可コードフローが全ケースで推奨される。
PKCE を扱う関連書籍も多い。
この記事は役に立ちましたか?
関連用語
OAuth 2.0
ユーザーのパスワードを渡さずに、リソースへの限定的なアクセスを許可する認可フレームワーク
OpenID Connect
OAuth 2.0 の上に構築された認証レイヤーで、ユーザーの身元情報を ID トークンとして提供する
Amazon Cognito
Web・モバイルアプリに認証・認可機能を追加する AWS マネージドサービス
リフレッシュトークン
アクセストークンの有効期限切れ後に、再認証なしで新しいアクセストークンを取得するためのトークン
ケイパビリティベースセキュリティ
リソースへのアクセス権を偽造不可能なトークン (ケイパビリティ) として管理するセキュリティモデル
BFF (Backend for Frontend)
フロントエンドごとに専用のバックエンドを用意し、クライアントに最適化された API を提供するパターン