OAuth 2.0
OAuth 2.0 の主要なフロー(特に安全に使うべき Authorization Code + PKCE)を中心に、図(テキスト図)で手順を示し、実装時に注意すべき点を箇条書きでまとめます。
要点(先に結論)
- ユーザー認可を安全に行うには「Authorization Code フロー + PKCE」を使う(公開クライアント=ブラウザ/ネイティブ向け)。
- サーバー間認証(マシン対マシン)は「Client Credentials」を使う。
- トークン取り扱い(保存・伝搬)とリダイレクト検証、TLS、スコープ設計が最重要。
- 認証(ユーザー識別)が目的なら OpenID Connect(OIDC)を併用する。
- Authorization Code フロー(推奨:PKCE付き) — テキスト図 クライアント = アプリ(例:SPA / ネイティブ / サーバーサイド) AS = Authorization Server(認可サーバ) RS = Resource Server(API)
ユーザーエージェント(ブラウザ)を介した典型フロー(PKCEあり):
- クライアント生成: code_verifier と code_challenge = HASH(code_verifier)
- ブラウザをリダイレクト → AS の認可エンドポイント GET /authorize?response_type=code&client_id=…&redirect_uri=…&scope=…&state=…&code_challenge=…&code_challenge_method=S256
- ユーザーが認可(ログイン、同意)
- AS がブラウザを redirect_uri?code=AUTH_CODE&state=… へリダイレクト
- クライアントが AUTH_CODE を受け取り、トークンエンドポイントへ POST(バックエンド): POST /token { grant_type=authorization_code, code=AUTH_CODE, redirect_uri=…, code_verifier=… }
- AS が code_verifier を検証 → アクセストークン(access_token) と(必要なら)リフレッシュトークン を返す
- クライアントが access_token を用いて RS に API リクエスト: Authorization: Bearer ACCESS_TOKEN
簡易ASCII図: User Browser Client Authorization Server Resource Server | | | | |—(1) open auth-> | | | |—(2) /authorize->|—- redirect —> | | | <—(4) redirect with code ————-| | | |—(5) POST /token-> | | | | <-(6) access_token–| | | |—(7) API call w/ token ———————> | | | | |
- Client Credentials フロー(マシン対マシン)
- クライアント(機械)が直接トークンを取得: POST /token { grant_type=client_credentials, client_id, client_secret, scope }
- AS は access_token を返す。ユーザーコンテキストは無し。
- その他のフロー(注意)
- Implicit フロー:クライアント側で直接トークンを受け取る方式。現在はセキュリティ上非推奨(PKCE 登場以降)。
- Resource Owner Password Credentials:ユーザー名/パスワードを直接クライアントに預ける方式。基本非推奨。
- OpenID Connect:認証が必要なら Authorization Code + OIDC (id_token) を使う。
- 実装で注意すべき点(チェックリスト)
- TLS(HTTPS)必須
- 認可エンドポイント・トークンエンドポイント・API は常に HTTPS のみ。
- PKCE の採用(公開クライアント用)
- code_verifier を使い、S256 を推奨。必須にする。
- state パラメータで CSRF 対策
- 生成・検証を必ず行い、一度のみ有効にする。
- redirect_uri を厳密に検証
- ワイルドカード禁止。登録済みの完全一致のみ受け入れる。
- クライアント認証
- 機密クライアント(サーバー)には client_secret または mTLS を必須にする。
- トークンの保管方法
- ブラウザ SPA は localStorage に保存しない(XSS に弱い)。
- 可能なら httpOnly, Secure, SameSite=strict クッキーを使う(ただし CSRF 対策が必要)。
- ネイティブアプリは OS の安全なストア(Keychain, Keystore)。
- アクセストークンの寿命を短く、リフレッシュは限定的に
- 短命アクセストークン + リフレッシュトークン回転(rotation)を推奨。
- リフレッシュトークンの再利用検出(reuse detection)を実装する。
- スコープの最小化
- 必要最小限の権限のみ付与。スコープで細かく分離する。
- トークンの検証(Resource Server)
- JWT: iss, aud, exp, nbf, iat をチェックし、署名(kid)を検証する。
- 署名鍵は公開鍵(JWKs)で取得してキャッシュ→ローテーション対応。
- オペレーションはトークンインスペクション(introspection)やJWT検証を用いる。
- Revocation(取り消し)と Logout
- リフレッシュトークンやアクセストークンの取り消しエンドポイントを用意する。
- ロギングと監査
- 異常なトークン発行やリフレッシュの試行をログし、アラート化する。
- エラーハンドリングをユーザーフレンドリーに
- 失敗時はユーザーに適切な再認証導線を示す。
- フロントエンドでの CORS と Cookie の扱い
- Cookie を使う場合は SameSite/HttpOnly を正しく設定、CORS の設定は最小権限で。
- セッション固定攻撃対策
- 新しい認可で既存セッションが乗っ取られないように、セッション ID を再生成するなど。
- リダイレクトURI の開発/本番の分離
- 登録済み URI を厳密に管理。誤ってワイルドカードや短縮URIを使わない。
- セキュリティ攻撃と対策(代表例)
- CSRF(認可リクエストの偽造)
- 対策:state パラメータ、SameSite cookie、CSRF トークン
- リダイレクト先にトークンが漏れる(referrer / history)
- 対策:認可コードフローを使いトークンを URL に含めない。Referrer-Policy ヘッダ。
- コードインターセプト(authorization code interception)
- 対策:PKCE を使用し、code_verifier で検証。
- XSS によるトークン窃取
- 対策:XSS を防ぐ(CSP, 入力検証等)。トークンを JS が読めない httpOnly cookie に保存。
- リフレッシュトークン盗難
- 対策:回転、再利用検出、最小権限、短寿命。
- 運用の注意
- 定期的に公開鍵や設定(.well-known/openid-configuration)を確認しキャッシュポリシーを設定する。
- 同意画面の文言は明確に(ユーザが何を許可するか分かるように)。
- 監査ログと異常検知(不審な IP、短時間に大量のトークン発行など)。
- ライブラリ利用:成熟した OAuth/OIDC ライブラリを使う(自前でプロトコル実装しない)。
- 規格のバージョン差違いに注意(RFC と実装の差)。
- 実装例(簡潔なベストプラクティス)
- Web サーバー(Confidential Client)
- Authorization Code (no PKCE necessary but allowed) → サーバーで code を交換 → access/refresh を安全にサーバー側で保管(DB、暗号化)。
- クライアントはセッション cookie を使ってユーザーセッションを管理。API 呼び出しはサーバー側が access_token を付与して行う(BFF パターン)。
- SPA(Public Client)
- Authorization Code + PKCE を使用。access_token はメモリか短期 cookie に保存、長期保存を避ける。できれば BFF(Backend For Frontend)を使ってブラウザにトークンを渡さない方法を検討。
- 推奨ライブラリ/仕様参照
- RFC 6749 OAuth 2.0(仕様)
- RFC 8252(ネイティブアプリ向け)
- OAuth 2.0 for Browser-Based Apps(IETF draft 推奨事項)
- OpenID Foundation の OIDC
- 実装ライブラリの例:
- サーバー:oauth2-proxy, Keycloak, Auth0, Okta, Hydra(ORY)
- クライアント:OAuth client libraries(各言語の公式・実績あるライブラリ)
最後に簡単な実践チェックリスト(最小限)
- HTTPS を全エンドポイントで有効にしている
- Authorization Code + PKCE を採用している(公開クライアント)
- state を使っている(検証している)
- redirect_uri を完全一致で検証している
- トークンの保存方法を安全に設計している(httpOnly cookie / OS keystore)
- アクセストークンを短時間にしている、リフレッシュトークンは回転している
- トークンの署名・検証(iss,aud,exp)をしている
- エラーログ・監査・異常検出を導入している
必要なら図をより見やすい形式(Mermaid や SVG)で作成しますが、表示可能か教えてください。あるいは、あなたの環境(SPA / ネイティブ / サーバーサイド / BFF)を教えてもらえれば、そのケースに合わせた詳細手順と実装サンプル(要求パラメータ、サーバー実装スニペット、CURL コマンド例)を出します。