代表的な面接トピック

バックエンド面接:OAuth 2.0 JWT-Secured Authorization Requestをどのように設計しますか?

バックエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

機密性の高いスコープやトランザクションコンテキストを扱うOAuthクライアント向けにJARを有効化する必要があります。Request Objectの発行と検証、鍵のローテーション、リプレイ保護を設計し、JARがPARやPKCEとどのように関連するかを説明してください。

プロンプトとコンテキスト

あなたはOAuth 2.0認可サーバーの責任者です。クライアントの認可リクエストには、価値の高いスコープ、リソースインジケーター、およびトランザクションコンテキストが含まれています。チームはサーバー側でリクエストの発信元と完全性を検証し、場合によってはそれらのパラメータを隠蔽したいと考えています。JWT-Secured Authorization Request(JAR)について、Request Objectのフォーマット、署名と暗号化、トランスポート、有効期限、鍵のローテーション、および障害処理を設計してください。

この質問は、アイデンティティ、決済、およびバックエンドの職種に適しています。RFC 9101は認可パラメータをJWTに格納します。JWSは完全性と送信元認証を提供し、JWEは機密性を提供できます。JARとPARの違いを明確に区別してください。JARはリクエストオブジェクトを保護するのに対し、PARはそれを認可サーバーに直接プッシュして参照を返します。

面接官がテストしていること

  • 認可エンドポイント、クライアント、キーディレクトリ、およびトークンエンドポイント間の責任の分離。
  • issuer、audience、アルゴリズム、時間クレーム、およびOAuthパラメータの検証。
  • 外部パラメータの競合、リプレイ、解凍や暗号リソースの濫用、および鍵ローテーションの処理。
  • JAR、PAR、PKCE、state、nonceに関する明確な脅威境界。
  • 可観測性(オブザーバビリティ)、ロールアウト、およびロールバック制御を通じた運用化。

明確化のための質問

  1. クライアントはパブリックですか、それともコンフィデンシャルですか?Request Objectにはクライアントが署名しますか、それとも信頼できるバックエンドが署名しますか?
  2. 完全性のみが必要ですか、それともブラウザや仲介者がスコープ、リソース、トランザクションフィールドを読み取れないようにする必要がありますか?
  3. 外部パラメータがJWTクレームを上書きすることはできますか?クライアントごとのrequestおよびrequest_uriのポリシーは何ですか?
  4. これはOIDCログイン、決済認可、または通常のOAuthですか?nonce、ステップアップ認証、否認防止監査は必要ですか?
  5. 鍵は静的に登録されていますか、JWKS経由で配信されていますか、それともHSMに保持されていますか?ローテーションと失効の目標値は何ですか?

30秒の回答

まず、誰がRequest Objectを発行できるか、そしてどの鍵とアルゴリズムが信頼されているかを確立します。issaudclient_idredirect_uriresponse_type、スコープ、時間クレーム、およびリプレイ識別子を検証します。完全性と送信元認証には許可リストにあるJWSを使用し、リクエストに機密性が必要な場合はJWEを追加します。保護されたJWTクレームを信頼できる唯一の情報源として扱い、外部パラメータとの競合は拒否します。サイズと有効期限を制限し、TTL付きでjtiを追跡し、検証が利用できない場合は高リスクなリクエストをフェイルクローズ(安全側に倒して拒否)にします。JARはオブジェクトを保護し、PARはトランスポートと参照の有効期限を保護し、PKCEは認可コードを引き換えるエンティティをバインドします。

詳細な回答

1. Request Objectの信頼境界の確立

クライアントはrequestでJWTを送信するか、PARを介して送信し後でrequest_uriで参照できます。認可サーバーはクライアント登録情報を使用して信頼できる発行者とアルゴリズムを選択します。JWTヘッダーにkidjkuが含まれているからといって、勝手に任意の鍵を取得してはいけません。

issaudclient_idredirect_uriresponse_type、スコープ、リソースなどのクレームは、登録情報および認可コンテキストと一致している必要があります。署名されていない外部の値によって署名された値が暗黙のうちに変更されてはならず、競合するまたは重複する重要パラメータは拒否されます。

2. JWS、JWE、およびアルゴリズムポリシーの選択

完全性と送信元認証が必要な場合はJWSを使用します。ブラウザや中間者が読み取るべきではないフィールドがリクエストに含まれている場合はJWEを使用します。アルゴリズムの許可リストを適用し、noneやアルゴリズムの切り替えを拒否し、ヘッダーサイズ、ネスト、総バイト数に上限を設けます。

JWEの受信者鍵は、信頼できる認可サーバーの登録情報から取得します。JWSの検証鍵は、クライアント登録情報または信頼できるJWKSディレクトリから取得します。復号、署名、クレームの失敗は単一のビジネスエラー境界を共有し、レスポンスが鍵やリクエストの存在に関する詳細を漏洩しないようにします。

3. クレームと時間枠の検証

issaudexp、および該当するnbfiatクレームを検証します。expは短く保ち、許容するクロックスキュー(時刻のずれ)は限定的な範囲にとどめます。監査とリプレイ検出のためにjtiまたは同等のユニークな識別子を使用し、2回目の使用を拒否するか再生成を要求します。

サーバーは依然として完全一致によるredirect-URIのマッチングを実行し、クライアントに許可されたレスポンスタイプとスコープをチェックします。有効なJAR署名は、ユーザーが認証されたことや同意したことを意味するわけではありません。セッション、同意、保証レベル、リスクの判断は認可エンドポイントの責任のままです。

4. 外部パラメータとリクエストソースの解決

仕様のパラメータ優先順位を適用する前に、リクエストソースをパースします。requestと通常のクエリパラメータが同時に現れる場合、署名されていない外部の値が保護されたJWTクレームを上書きしてはなりません。不一致、重複、または重要クレームの欠落がある場合はinvalid_requestを返します。

PARを使用する場合、クライアントはRequest Objectを認可サーバーに直接送信し、サーバーは短期間有効なrequest_uriを返します。その後、ブラウザは参照のみを運ぶため、URLの漏洩や長さ制限の問題が軽減されます。PARはJARの署名や暗号化を置き換えるものではなく、JAR自体が参照の有効期限を管理するわけでもありません。

5. リプレイ、すり替え、リソース乱用への耐性

クライアントIDとjtiを組み合わせたものをTTLストアの重複排除キーとして使用します。高リスクなフローでは1回限りの消費を必須とすることができます。JWTのサイズ、ネスト、復号時のCPU負荷、およびJWKSのリフレッシュ頻度に上限を設け、暗号処理と圧縮の乱用を制限します。

Request ObjectをクライアントおよびリダイレクトURIにバインドします。PKCE、state、OIDCのnonceと組み合わせることで、認可コードの横取り、セッションCSRF、認証レスポンスのすり替えに対処します。完全なJWT、トランザクションフィールド、クライアントアサーションを決してログに記録しないでください。

6. 鍵ディレクトリとローテーションの設計

各クライアント検証鍵および各認可サーバー暗号化鍵に、バージョン、用途、ステータスを割り当てます。JWKSキャッシュには明示的なTTLが必要です。ローテーション中は新しい鍵を公開し、発行者を切り替え、リクエストまたはトークンの最大有効期間の間は古い鍵を保持してから失効させます。

kidが見つからない場合は、無制限に外部へリトライするのではなく、制御されたディレクトリリフレッシュを1回だけ許可します。鍵の失効、ディレクトリの停止、アルゴリズムの不一致にはメトリクスとアラートが必要です。検証を完了できない場合、高リスククライアントはフェイルクローズします。

7. 可観測性、ロールアウト、ロールバックの追加

暗号文や完全なトークンは決して記録せず、リクエストオブジェクトのハッシュ、クライアント、アルゴリズム、検証結果、ハッシュ化されたjti、およびレイテンシを記録します。署名や復号の失敗、クレームの競合、有効期限切れ、重複したjti、JWKSのリフレッシュ、および認可の完了を追跡します。

クライアントごとにJARを有効化し、完了率、レイテンシ、エラー分布を従来のフローと比較し、キーディレクトリまたは互換性のシグナルが悪化した場合はロールアウトを一時停止します。ロールバックは明示的に承認されたポリシーを復元するべきであり、署名されていない外部パラメータを高リスクスコープのフォールバックにしてはなりません。

模範解答

私はJARを、認可リクエストの完全性と機密性を確保するレイヤーとして扱います。クライアントまたは信頼できるバックエンドが、登録情報に従ってRequest Objectを作成します。認可サーバーは許可リストにあるアルゴリズムと信頼できる鍵のみを受け入れ、issuer、audience、クライアント、redirect URI、response type、スコープ、iat/expjtiを検証し、保護されたクレームと競合する未署名の外部の値を拒否します。完全性と送信元認証にはJWSを使用し、機密性にはJWEを使用します。

オブジェクトに短い有効期間とクライアントバインディングを設定し、TTLを使用してjtiを重複排除し、サイズ、ネスト、復号リソースを制限します。ローテーション中のオーバーラップ期間を設けて、バージョン管理されたJWKS鍵を使用します。JARはPARと組み合わせることができます。JARはオブジェクトを保護し、PARはブラウザのパラメータを隠蔽して参照を管理し、PKCE、state、nonceはそれぞれのコードおよびセッションバインディングを維持します。

検証失敗、リプレイ、JWKSリフレッシュ、完了率、レイテンシを監視しながら、クライアントごとにロールアウトします。キーディレクトリの障害や検証不能な高リスクリクエストはフェイルクローズします。ロールバックは定義済みの古いポリシーを復元し、署名されていない外部パラメータを同等の保護として扱うことは決してありません。

よくある間違い

  • issuer、audience、アルゴリズム、時間、redirect URIをチェックせずに「JWT署名は安全である」と述べること。
  • kidまたはjkuによって任意のネットワークキー取得をトリガーさせ、信頼範囲とSSRFリスクを拡大させること。
  • 外部のクエリ値によって署名されたスコープやredirect URIが上書きされるのを許可すること。
  • リクエスト、トランスポート、コードの保護として個別に捉えず、JAR、PAR、PKCEを単一の機能として扱うこと。
  • jti、短いTTL、サイズ上限、暗号リソース制限を省略すること。
  • ローテーション中に古い鍵を即座に削除し、まだ有効なリクエストを破損させること。
  • 検証失敗後に通常の認可へ無条件でフォールバックすること。

フォローアップの質問と回答

クライアント署名と認可サーバー署名の違いは何ですか?

クライアント署名により、サーバーはリクエストの送信元を認証し、改ざんを検知できます。サーバー署名は通常、ダウンストリームにサーバーの構成証明を伝達します。それぞれのトラストアンカー、鍵の用途、ローテーションの管理者が異なります。

JARが署名されている場合でも、なぜPKCEが必要なのですか?

JARはリクエストの内容を保護します。PKCEは認可コードを引き換える当事者を保護します。ブラウザのコールバックが傍受された場合でも、verifierが依然として必要です。

すべてのパラメータをJWT内に含める必要がありますか?

完全性、送信元認証、または機密性が必要なパラメータをRequest Objectに配置します。許可される外部パラメータの優先順位を定義し、競合や重要な値の欠落を拒否します。

JWKSが一時的に利用できない場合はどうなりますか?

短期間のキャッシュと1回の制御されたリフレッシュを使用します。信頼できる鍵が利用できない場合は、高リスクなリクエストに対してフェイルクローズし、アラートを発報します。可用性のために未知の鍵を受け入れたり、検証をスキップしたりしてはいけません。

通常のリクエストのみをサポートするクライアントをどのように移行しますか?

クライアントメタデータを介してJARを有効化し、検証と完了を測定してから、移行済みクライアントに対してJARを必須にします。古いフローについて、残りのスコープ、リスク制限、およびサンセット(廃止)日を明示的に構成します。

機密性の高いJWTがログに含まれていないことをどのように証明しますか?

ゲートウェイ、認可サービス、エラー追跡ツールでフィールドのマスキング(リダクション)を適用します。オブジェクトとjtiのハッシュ、クライアント、結果のみを保持します。ログをサンプリングし、トークン、暗号文、トランザクションフィールドを拒否するリグレッションチェックを実行します。

公開情報ソース

関連する質問