secure-oauth-oidc について
OAuthとOpenID Connectのフローを設計、実装、レビューするためのセキュリティスキルです。RFC 9700の基準、トランザクションの結び付け、トークン検証など、プロトコル全体の不変条件を扱います。
主な機能
- 01RFC 9700セキュリティ基準
- 02認可フローのトランザクション台帳
- 03リダイレクト、コード、トークン境界の制御
- 04OIDCのIDとID Tokenの検証
- 05設計、実装、レビューの手順
活用シーン
- 01認可コードフローのレビュー
- 02OAuthまたはOIDC移行の設計
- 03トークン処理のネガティブセキュリティテスト追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ citypaul/ .dotfiles --skill secure-oauth-oidcインストール後、Claude Code で/secure-oauth-oidcを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlreferences/attack-and-test-catalog.mdoidc-validation.mdreview-and-delivery.mdrfc9700-control-catalog.mdstandards-map.md詳細
セキュアな OAuth と OpenID Connect
OAuth のセキュリティは、パラメーターのチェックリストではなく、エンドツーエンドのプロトコル不変条件の集合として扱ってください。RFC 9700 / BCP 240 をベースラインとし、選択した OAuth 拡張機能、OpenID Connect、プラットフォームプロファイル、デプロイに関する要件を追加してください。
OAuth はアクセスを委譲します。OpenID Connect は認証を追加します。OAuth だけを根拠にログイン ID を推測してはならず、アクセストークンを ID Token として使用してはなりません。
このスキルが担うのは OAuth/OIDC プロトコル層です。ブラウザーに対応する BFF に関連するアプリケーションセッション(セッション Cookie、CSRF とブラウザーリクエストポリシー、公開/保護エンドポイントの分類、ブラウザーからのトークンの隔離)については、bff-entry-points スキルを読み込んでください。
変更するフローをベースラインに適合させる
認可コードフローの一部を追加、拡張、経路変更、または参照先変更する変更では、同じ変更内でそのフロー全体を RFC 9700 のベースラインに適合させてください。具体的には、トランザクションごとの検証子を使う S256 PKCE、使い捨ての新しい state、OIDC の場合は nonce(どちらもサインインを開始したブラウザーにバインド)、完全一致するリダイレクト URI、使用するすべてのトークンでの発行者とオーディエンスの検証、そして URL、ログ、ブラウザーから読み取れる情報へのトークンの記録を禁止することです。
依頼の範囲が狭く書かれていること、リポジトリにある ToDo リストや引き継ぎメモ、現状の形を固定する既存テスト、あるいは不具合があなたの担当以前から存在していたという事実は、そのフローをベースライン未満の状態にしておく理由にはなりません。隣接する安全でないフローに合わせて新しいフローを構築してはならず、すでに編集しているファイルや関数に残る露出を放置してはなりません。残存リスクとして列挙するのは、この変更で触れなかったものだけです。
適切なリファレンスを読み込む
| リファレンス | 読み込むタイミング |
|---|---|
references/rfc9700-control-catalog.md | セキュリティ設計またはレビューでは常に読み込みます。要件の強さ、適用可能性、セクションの出典が記載されています |
references/attack-and-test-catalog.md | 脅威モデリング、インシデント分析、敵対的レビュー、またはネガティブテストの作成時 |
references/oidc-validation.md | OIDC、ID Token、UserInfo、Discovery、マルチ発行者、またはフェデレーションログインに関する作業時 |
references/review-and-delivery.md | 実装の監査、指摘事項の報告、修正計画、または完了を示す証拠の定義時 |
references/standards-map.md | 拡張機能/プロファイルの選択、情報源の優先順位の解決、または標準が安定していて最新かどうかの確認時 |
タスクに必要なリファレンスだけを読み込んでください。コントロールカタログに正確な規範的文言が記載されている場合は、記憶に頼らないでください。
まずセキュリティプロファイルを特定する
コードや設定を推奨する前に、次の点を特定してください。
- 目的 — 委任された API アクセス、ユーザー認証、その両方、マシン間アクセス、デバイス認可、またはトークン交換。
- 関係者 — 認可サーバー/OpenID Provider、クライアント/Relying Party、リソースサーバー、リソースオーナー/エンドユーザー、ブラウザーまたはシステムユーザーエージェント、TLS 終端を行う中継者。
- クライアントの種類と実行コンテキスト — confidential または public、サーバーサイドの Web アプリ、ブラウザーアプリ、ネイティブアプリ、サービス、CLI、またはデバイス。登録時のラベルではなく、認証情報を実際に機密に保てるかどうかで分類してください。
- フローとレスポンスモード — 有効になっているすべての grant、response type、response mode、コールバック、トークン交換、更新経路、ログアウト経路、バックチャネル呼び出しを、レガシーな経路も含めて列挙してください。
- 信頼トポロジー — issuer が単一か複数か、ディスカバリー/登録が静的か動的か、リソースサーバーが単一か複数か、コンポーネントが同一パーティかサードパーティか、プロキシやサービスメッシュの有無。
- 適用するプロファイル — RFC 9700 のベースラインに加え、OIDC Core、ネイティブアプリの BCP、DPoP、mTLS、PAR/JAR/JARM、FAPI、またはその他のデプロイメントプロファイル。より厳格なプロファイルは要件を追加するものであり、ベースラインを無効にするものではありません。
- 証拠 — 正確なコード、設定、メタデータ、ライブラリとバージョン、テスト、実行時の動作。調査していないものには「不明」と明記してください。
タスクの説明が不十分な場合は、まずリポジトリとデプロイ済みのメタデータを調査してください。プロファイルを大きく左右し、安全に確認できない選択肢についてのみ質問してください。
トランザクション台帳を作成する
各フローを開始からコールバック、トークンの使用、更新、失効、ログアウトまで追跡します。各アーティファクトについて、作成、保存、送信、検証、消費、有効期限切れ、無効化を行う主体を記録してください。
| アーティファクト | 必須のバインディングまたは検証 |
|---|---|
| 認可リクエスト | 想定する issuer、クライアント、正確なリダイレクト URI、response type/mode、要求するリソースと権限 |
state | 十分なエントロピーを持ち、一度だけ使用され、開始元のユーザーエージェントセッションに安全に紐付けられていること。アプリケーションの状態を含む場合は完全性が保護されていること |
| PKCE verifier/challenge | トランザクション固有であること。verifier の秘密情報は開始元のクライアントインスタンスが保持すること。S256 を使用すること。認可サーバーが challenge の有無を記録すること |
OIDC nonce | トランザクション固有で、開始元のセッションに紐付けられていること。返されたトークンを使用する前に、正しい ID Token で検証すること |
| 認可レスポンス | 想定するセッション、issuer、リダイレクトエンドポイント、response mode、エラー/成功の意味 |
| 認可コード | クライアント、リダイレクト URI、トランザクション/PKCE challenge に紐付けられていること。一度だけ使用され、有効期間が短いこと |
| アクセストークン | issuer、対象リソース/audience、権限、有効期間、トークンタイプ、制約付きの場合は送信者鍵 |
| リフレッシュトークン | クライアントインスタンス、grant、同意済みの scope/リソース、リプレイ検出ファミリーまたは送信者鍵、有効期限/失効状態 |
| ID Token | 想定する issuer、Relying Party の audience、署名/アルゴリズム、時刻クレーム、nonce およびフロー固有のハッシュ |
バインディングが欠落していたり暗黙的だったりする箇所には、ミックスアップ、CSRF、認可コードインジェクション、トークン置換、リプレイ攻撃が潜んでいます。
RFC 9700 のベースラインを適用する
正確な文言と条件については、管理策カタログを参照してください。少なくとも、次の境界を確認してください。
リダイレクトと認可の境界
- 登録済みのリダイレクト URI と完全一致する文字列のみを許可します。RFC 8252 で定義されたネイティブのループバックポートの例外のみを認め、ホスト、パス、スキーム、その他のクライアントに一般化してはなりません。
- クライアントと認可サーバーの両方で、オープンリダイレクターを拒否します。
- 狭く定義されたネイティブのループバックのケースを除き、暗号化されていない接続で認可レスポンスを送信してはなりません。
- トランザクションに結び付いた仕組みで CSRF を防止します。PKCE をこの役割に使えるのは、対応していることが確認できた後に限ります。それまでは、ワンタイムでセッションに結び付いた
state、または保証が適用される場合は OIDC のnonceを使用します。 - 複数の発行者を使用するクライアントでは、選択した発行者をユーザーエージェントのセッションに結び付け、認可レスポンス内の発行者を検証します。RFC 9207 の
iss、または同等の署名付きレスポンスを優先します。代替策は、異なるリダイレクト URI を使用することです。 - 認証情報を含むフォーム送信の後に HTTP 307 を使用してはなりません。HTTP リダイレクトには 303 を使用します。
認可コードの境界
- パブリッククライアントには PKCE を必須とし、コンフィデンシャルクライアントにも推奨します。適用されるプロファイルに別段の定めがない限り、すべての認可コードクライアントで PKCE をデフォルトで使用します。
S256を使用し、ベリファイアとチャレンジをトランザクションごとに固有のものにして、ベリファイアを必ず検証します。また、認可リクエストにチャレンジがなかった場合にベリファイアを含むトークンリクエストを拒否します。- 認可コードの有効期間を短くし、1 回のみ使用できるようにします。2 回目の交換は侵害の兆候として扱い、認可サーバーはそのコードに基づいて以前に発行したすべてのトークンを失効させるべきです(SHOULD)。
- クライアント認証を、コードインジェクションに対する保護と取り違えてはなりません。正規のコンフィデンシャルクライアントが、注入されたコードを交換できてしまう可能性があります。
トークンの境界
- リソースオーナー・パスワード・グラントを使用してはなりません。指定されたすべてのインジェクションと漏えいの経路が確実に緩和されている場合を除き、インプリシットフローや、認可エンドポイントからアクセストークンを返すあらゆるレスポンスを避けます。
- URI のクエリパラメーターにアクセストークンを含めてはなりません。
- アクセストークンはリソース/オーディエンスと最小権限に基づいて制限し、各リソースサーバーにその両方を強制させます。
- DPoP または mTLS を使用して、送信者制約付きアクセストークンを優先します。リソースサーバーでトークンのバインディングと証明の両方を検証します。バインドされたトークンを所持しているだけでは不十分です。
- パブリッククライアントでは、リフレッシュトークンを送信者に制約するか、再利用検出を伴ってローテーションします。すべてのリフレッシュトークンを、同意されたスコープおよびリソースサーバーに結び付けます。
- ストレージ、転送、ログ、トレース、エラー、URL、分析データ、テスト用フィクスチャにおいて、トークンを秘密情報として扱います。適用されるプラットフォーム/プロファイルが裏付ける範囲を超えて、ストレージに関する主張を断定的にしてはなりません。脅威と根拠を説明します。
デプロイの境界
- 認可サーバーのメタデータを公開して利用し、発行者を検証します。発行者間でエンドポイントや鍵を混在させてはなりません。
- TLS 終端プロキシでは、攻撃者が指定したセキュリティヘッダーを削除または上書きし、盗聴、インジェクション、リプレイからプロキシとアプリケーション間の通信を保護します。
- CSP の
frame-ancestorsと適切な互換性対策を用いて、認可、ログイン、同意、デバイス、エラーページでのクリックジャッキングを防ぎます。 - Referer データを受け取る可能性のあるサードパーティーリソースを、認可ページとコールバックページから排除します。意図を明確にした Referrer Policy を設定します。
postMessageフローでは、登録済みの正確なターゲットオリジンを使用し、*は決して使用しません。送信元オリジンを厳密に検証し、通常の認可レスポンスに対するすべての制御を適用します。- 認可エンドポイントで CORS を有効にしてはなりません。CORS は OAuth の CSRF 対策ではありません。
OIDC のアイデンティティレイヤーを追加する
OIDC の作業では、references/oidc-validation.md を読み込み、次の 3 つの役割を分けて扱います。
stateは認可レスポンスを関連付け、クライアントのコールバックを保護します。- PKCE は認可コードを開始元のクライアントインスタンスに紐付けます。また、サポートが確実な場合は CSRF から保護できます。
nonceは ID Token を認証トランザクションに紐付けます。また、RFC 9700 に明記された条件の下では、機密性の高い OIDC クライアントをコードインジェクションから保護できます。
ID Token は、単なる署名付き JWT ではなく、プロトコルオブジェクトとして検証します。ローカルアカウントを (iss, sub) に紐付け、リライングパーティーのオーディエンスと認可パーティーを検証し、時刻と nonce のセマンティクスを適用し、必要な場合はフロー固有のトークンハッシュを検証し、UserInfo の sub が ID Token の sub と一致することを必須とします。
特定のアクセストークンプロファイルによってサポートされる契約が定められていない限り、クライアントでアクセストークンを解析してアイデンティティを確認しないでください。有効な JWT アクセストークンであっても、宛先はリライングパーティーではなくリソースサーバーです。
タスクの進め方を選ぶ
設計または移行
- セキュリティプロファイルと、信頼境界図またはフローのトレースを作成します。
- 各トランザクションの紐付けと、トークン検証の不変条件を明示します。
- 任意の強化策を追加する前に、安全でないグラントを削除します。
- 相互運用可能な制御を選び、最新の一次資料を参照してプロバイダーとライブラリのサポートを確認します。
- 実装前に、否定テストと可観測性を定義します。
- 移行では、すべてのクライアントとコールバックを棚卸しし、互換性を慎重に段階導入し、ロールバックを定義するとともに、より弱い移行モードには期限を設定します。
実装
- プロトコルや暗号処理を独自に実装せず、保守されている OAuth/OIDC ライブラリを使用します。
- ライブラリの正確なバージョンと設定経路を調べます。デフォルト設定やメソッド名は、根拠にはなりません。
- 信頼境界で検証し、セッションを作成したりトークンを転送したりする前に、フェイルクローズにします。
- シークレットや生のトークンをテレメトリに含めないでください。代わりに、安全な識別子、判定理由、発行者、クライアント ID、オーディエンス、グラントタイプ、リプレイイベントを記録します。作業対象のファイルに、生のトークン、コード、またはベリファイアをログ出力したり返したりする既存の行があれば、触れた時点ですぐに削除してください。露出を回避するだけの修正は、結局その露出を含む状態で出荷したのと同じです。また、URL、レスポンスボディ、ログにトークンが現れることを検証するテストは書かないでください。
- 振る舞いに基づく肯定テストと否定テストを追加します。本番コードを変更する場合は、利用可能であればリポジトリのテスト/TDD ワークフローを使用します。
レビューまたはインシデントの診断
- 攻撃者の能力から資産と影響まで、攻撃経路をたどります。該当することを確認せずに、パラメーターがないことだけを報告しないでください。
- 規範への不適合、悪用可能な弱点、多層防御の不備、不明を区別します。
- 根拠として、ファイル/行、設定経路、メタデータフィールド、HTTP トレース、または再現可能なシナリオを示します。すべての認証情報とトークン値を伏せてください。
- インシデント時には、証拠を保全し、トークン/コード/認証情報の露出を封じ込め、影響を受けたグラントまたはトークンファミリーを失効させ、侵害されたキーをローテーションしてから、原因となった制御を修正します。証拠を破棄したり、許可されていないシステムを調査したりしないでください。
- 報告書と完了条件には、
references/review-and-delivery.mdを使用します。
誤った安心感を与える説明を退ける
stateが存在するだけでは保護になりません。予測不能で、一度限りであり、検証され、開始元のセッションにひも付けられている必要があります。- PKCE はクライアント認証ではなく、発行者を検証せず、任意の認可リクエストの改ざんを防ぐものでもありません。
- OIDC の
nonceは汎用的な純粋な OAuth 防御策ではなく、公開クライアントの盗まれたコードを攻撃者が引き換えることも防ぎません。 - TLS では、エンドポイントの取り違え、ブラウザー履歴、Referer の漏えい、オープンリダイレクト、侵害されたエンドポイントを防げません。
- JWT の署名が有効であっても、期待される発行者、オーディエンス、トークン種別、有効期限、nonce、認可が正しいとは証明されません。
- DPoP や mTLS も、攻撃者がトークンと利用可能な鍵の素材の両方を入手した場合には役立ちません。XSS やクライアントの侵害によって、この境界が崩れる可能性があります。
- CORS、SameSite Cookie、ブラウザーコード内のクライアントシークレット、パラメーターの隠蔽は、プロトコル上のひも付けの代わりにはなりません。
- プロバイダーで正常系が成功しても、それはセキュリティの証拠にはなりません。悪意あるリダイレクト、リプレイ、発行者のすり替え、検証失敗を試してください。
提出要件
以下を返してください。
- スコープとプロファイル — 関係者、クライアント種別、フロー、発行者、リソース、適用される標準。
- フローと信頼境界 — 成果物のひも付けと検証ポイント。
- 検出事項または設計上の決定 — 要件の強度、証拠、攻撃シナリオ、修正策、検証。
- 充足が確認された制御 — 証拠で裏付けられたものに限ります。
- 不明点と前提 — 証拠が不足している場合、適合していると暗黙に見なしてはなりません。
- テストと実行時チェック — 正常系、異常系、リプレイ、失敗経路の網羅。
- 残存リスクと移行上の制約 — 例外、責任者、有効期限を明示してください。
正常系テストがすべて成功した、またはチェックリストのすべての項目を埋めたという理由だけで、OAuth/OIDC システムを安全だと宣言してはなりません。検査した証拠が立証する範囲に限って宣言してください。