認可コードフロー
最も標準的で安全なフロー。サーバーサイドアプリケーションに適しています。認可コードを中間的な資格情報として使用し、バックチャネルでトークンを取得します。
シーケンス図
各ステップの詳細
ブラウザ → 認可サーバー
クライアントがブラウザを認可サーバーの認可エンドポイントにリダイレクトします。
リクエスト
GET /authorize
response_type=code&client_id=my-app&redirect_uri=https://example.com/callback&scope=openid profile&state=random-csrf-token
セキュリティノート
- !state パラメータでCSRF攻撃を防止する
- !redirect_uri は事前登録されたものと完全一致させる
認可サーバー → ブラウザ
認可サーバーがユーザーにログイン画面と同意画面を表示します。ユーザーが認証し、要求されたスコープへのアクセスを許可します。
リクエスト
GET /login
レスポンス
POST /login
username=user&password=****&consent=approve
セキュリティノート
- !認可サーバーのドメインでのみ認証が行われる
- !クライアントはユーザーの資格情報に触れない
認可サーバー → クライアント
認可サーバーが認可コード付きのリダイレクトURIにブラウザをリダイレクトします。認可コードは一時的で短命です。
リクエスト
GET https://example.com/callback
code=SplxlOBeZQQYbYS6WxSbIA&state=random-csrf-token
セキュリティノート
- !認可コードは短命(通常10分以内)
- !state の値を検証してCSRF攻撃を防ぐ
- !認可コードは1回のみ使用可能
クライアント → 認可サーバー
クライアントがバックチャネル(サーバー間通信)で認可コードをトークンエンドポイントに送信します。
リクエスト
POST /token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic base64(client_id:client_secret)
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https://example.com/callback
セキュリティノート
- !バックチャネル通信のためブラウザを経由しない
- !client_secret による認証でクライアントの正当性を確認
認可サーバー → クライアント
認可サーバーがアクセストークン(とオプションでリフレッシュトークン)を返します。
リクエスト
POST /token
レスポンス
200 /token
{ "access_token": "eyJhbGciOiJSUzI1NiIs...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g...", "scope": "openid profile" }
セキュリティノート
- !トークンはバックチャネルで安全に受け取る
- !アクセストークンは有効期限を設定する
クライアント → リソースサーバー
クライアントがアクセストークンを使用してリソースサーバーにアクセスします。
リクエスト
GET /api/userinfo
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
レスポンス
200 /api/userinfo
{ "sub": "user123", "name": "山田太郎", "email": "taro@example.com" }
セキュリティノート
- !Bearer トークンは Authorization ヘッダーで送信
- !リソースサーバーはトークンの有効性を検証する
- +サーバーサイドWebアプリケーション
- +client_secret を安全に保管できる環境
- +最も一般的で推奨されるフロー
- -SPA(シングルページアプリケーション)→ PKCE を使用する
- -ネイティブアプリ → PKCE を使用する
- -サーバー間通信 → クライアントクレデンシャルを使用する
セキュリティ上の考慮事項
- !認可コードは短命で1回のみ使用可能にする
- !state パラメータで CSRF 攻撃を防止する
- !redirect_uri は完全一致で検証する
- !client_secret はサーバーサイドで安全に管理する
- !HTTPS を必ず使用する