代表的な面接トピック

バックエンド面接:OAuth 2.0のステップアップ認証チャレンジをどのように設計しますか?

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

質問

あなたのAPIは低リスクな読み取りを許可していますが、送金や受取先口座の変更にはより強固な認証が必要です。エラー、認証コンテキスト、リトライ、トークン検証、およびダウングレード境界を網羅するOAuthステップアップチャレンジを設計してください。

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

リソースサーバーは読み取りに対して通常のアクセストークンを受け入れますが、送金、受取先口座の変更、機密性の高いエクスポートには、より高い認証レベルを必要とします。クライアントがそのレベルを満たしていない場合、曖昧な403ではなく、アクションにつながるチャレンジを受け取る必要があります。RFC 9470を使用して、リソースサーバー、認可サーバー、クライアント間のステップアップフローを設計してください。

RFC 9470はBearerチャレンジにおけるinsufficient_user_authenticationエラーを定義し、要求されるレベルを表すためにacr_valuesまたは関連する認証コンテキストを使用します。面接では、APIエラー、トークンクレーム、再認可、冪等なリトライ、ダウングレード境界にわたる完全なループがテストされます。

面接官が見ているポイント

  • 認可の失敗、ユーザー認証の不足、トークンの有効期限切れの区別。
  • 内部のリスク詳細を公開することなく、WWW-Authenticateで要求される認証コンテキストを表現すること。
  • ループやダウングレードを防ぎつつ、クライアントがチャレンジから再認可を行えるようにすること。
  • リソースサーバー側での発行者(issuer)、対象者(audience)、スコープ(scope)、acramr、および時間関連クレームの検証。
  • 高リスクな書き込みに対するリトライ、並行性、監査、ロールバック、およびユーザー体験の処理。

確認すべき質問

  1. どの操作がより高いレベルを要求し、その要件はacramr、またはトランザクション確認のどれですか?
  2. アクセストークンはローカル検証されるJWTですか、それともイントロスペクションされますか?リソースサーバーは認証コンテキストを確認できますか?
  3. クライアントはWeb、モバイル、サーバーアプリケーションのどれですか?PKCE、prompt、max_ageは利用可能ですか?
  4. チャレンジは1回限りで、金額、受取人、およびnonceにバインドされるべきですか?
  5. 認可サービスが利用できない場合、どの読み取りが継続可能で、どの書き込みがフェイルクローズ(fail closed)である必要がありますか?

30秒の回答

まずトークンの発行者、対象者、署名、有効期限、スコープを検証します。スコープが十分であるにもかかわらず認証コンテキストが不足している場合は、insufficient_user_authenticationと要求されるacr_valuesおよびリソースを指定したWWW-Authenticate Bearerチャレンジとともに401を返します。クライアントは意図と状態を保持し、再認証を行い、同一の対象者、スコープ、コンテキストにバインドされたトークンを受け取って1回リトライします。チャレンジには短いTTL、制限されたリトライ回数、トランザクションバインディングを設定し、高リスクな操作を決して暗黙的にダウングレードしないようにします。

詳細な解説

1. 認証ポリシーとリソースポリシーの定義

操作を最小認証ポリシーにマッピングします。読み取りには基本レベル、受取先口座の変更にはフィッシング耐性のある認証、送金にはトランザクション確認を適用します。すべての書き込みを一律の固定レベルと同一視するのではなく、エンドポイント、メソッド、テナント、金額、およびリスクシグナルを評価します。

認可サーバーは登録済みのacr値と受け入れ可能な認証方式を定義します。リソースサーバーは登録済みの値のみを受け入れ、クライアントが自身で上位レベルを自己主張することはできません。amrは証拠であり、acrのポリシー評価に代わるものではありません。

2. チャレンジレスポンスの設計

有効なトークンに必要なコンテキストが不足している場合、401とerror="insufficient_user_authentication"を含むBearerチャレンジを返します。これには要求されるacr_values、リソース識別子、およびエラーURIを含めることができますが、口座番号、リスクスコア、内部ルールを漏洩してはなりません。

コンテキストが欠落しているか検証不能な場合は不足として処理します。トークン期限切れ、信頼できない発行者、誤った対象者、スコープ不足に対しては明確に異なるエラーを使用し、すべての失敗をステップアップとして偽装しないようにします。

3. クライアントによる再認可の許可

クライアントはチャレンジをパースし、元のターゲット、要求されたacr_values、リソース、およびPKCEを新しい認可リクエストにバインドします。Webクライアントはstateを使用し、OIDCクライアントはnonceを使用します。モバイルクライアントは未検証のチャレンジを実行可能な認可URLとして扱ってはなりません。

再認可には依然として認可サーバーでの認証と同意が必要です。promptmax_age、または認証ポリシーはリクエストにすぎません。サーバーは実際の認証に基づいて達成されたacrをトークンに書き込みます。クライアントがローカルでトークンをアップグレード済みとしてマークすることはできません。

4. 新しいトークンと元の意図の検証

新しいトークンの署名、発行者、対象者、スコープ、expiatacr、および要求されたamrを検証します。イントロスペクションを使用する場合は、十分なコンテキストを含む信頼できる認可サーバーのレスポンスを要求します。権限と認証強度は別次元であるため、スコープ単体では不十分です。

高リスクなアクションに対しては、チャレンジnonce、トランザクションダイジェスト、または認可リクエストIDをサーバー状態にバインドし、より高い認証トークンが別のトランザクションに流用されないようにします。トークンの対象者は対象APIに対して厳密に維持します。

5. ループ、リプレイ、ダウングレードの防止

各チャレンジに短いTTLと一意のIDを付与し、リクエストダイジェスト、テナント、リソース、要求レベル、リトライ回数を記録します。1回または制限された少数のリトライを許可し、成功したチャレンジは消費(無効化)し、失敗または期限切れのチャレンジは終了させます。

より低いacr_values、リソースや対象者の置き換え、ステップアップのタイムアウト後に通常のトークンへフォールバックすることを拒否します。送金には冪等性キーを使用し、認証のリトライによって副作用が重複しないようにします。

6. 可用性とエラー境界の処理

認可サービスまたはイントロスペクションが利用できない場合、低リスクな読み取りは短いキャッシュを使用できますが、書き込み、支払い、権限変更はデフォルトでフェイルクローズとします。チャレンジエラーによって認証方式や口座の状態が公開されてはなりません。ログにはチャレンジID、発行者、結果、レイテンシを保持します。

不十分なコンテキストの発生率、チャレンジ完了率、ループ、期限切れ、リプレイ、PKCE失敗、acrによる拒否、重複したビジネス上の副作用を追跡します。ポリシーエラーと攻撃を区別するために、リソースおよびテナントごとにアラートをセグメント化します。

7. 安全なロールアウトとロールバック

まず単一のAPIとテナントでステップアップを有効化し、401エラー、完了率、レイテンシ、サポートへのフィードバック、高リスクな拒否を比較します。チャレンジを認識しないクライアントにはドキュメント化されたエラーとSDKガイダンスを提供し、通常のトークンを全員に対して暗黙的に受け入れないようにします。

ロールバックでは、まだ有効化されていないリソースポリシーのみを無効化し、アクティブなトランザクションのためのチャレンジ状態と監査ログは保持します。コンテキストの漏洩、副作用の重複、またはループが発生した場合は、ロールアウトを一時停止し、ポリシーを取り消してトークンバインディングを再確認します。

模範解答

各操作に対して最小認証レベルを定義します。トークンを検証した後、スコープは十分であるもののacrまたはamrが不足している場合、リソースサーバーはinsufficient_user_authentication、最小限のacr_values、リソース、およびエラーURIを含む401を返します。クライアントは意図を保持し、state、nonce、PKCEを使用して再認可を行います。認可サーバーは実際の認証を反映したコンテキストを持つトークンを発行します。

リソースサーバーは発行者、対象者、スコープ、時間、acr、および要求されるamrを再度検証し、チャレンジIDまたはトランザクションダイジェストをサーバー状態にバインドします。チャレンジは短寿命、1回限り、リトライ制限付きとし、下位レベル、新しい対象者、無条件のフォールバックは拒否されます。認証障害時、高リスクな書き込みはフェイルクローズとし、送金には冪等性キーを使用します。

よくある落とし穴

  • アクション可能なinsufficient_user_authenticationチャレンジではなく、一般的な403または401を返してしまう。
  • スコープのみをチェックし、発行者、対象者、acramr、および時間クレームを確認しない。
  • クライアントがより高いacrを自己主張したり、チャレンジ後に引き下げたりすることを許可してしまう。
  • チャレンジを未検証の認可URLとして扱い、state、nonce、PKCEをスキップしてしまう。
  • 無限にリトライしたり、トランザクションバインディングを省略して、操作間でトークンが再利用されるのを許してしまう。
  • 認証が利用できない場合に、送金や権限変更を暗黙的にダウングレードしてしまう。
  • 口座情報、リスクスコア、完全なトークンをログに記録してしまう。

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

スコープが十分であるにもかかわらず、なぜacr不足で401を返すのですか?

スコープはトークンがアクセスできる対象を示し、acrはユーザーがどのように認証されたかを示します。リソースは両方を要求する場合があるため、クライアントには新たな認可ステップが必要になります。

チャレンジには何を含めるべきですか?

クライアントのアクションに必要な要求認証レベル、リソース識別子、エラーURI、および短寿命のチャレンジ識別子のみを含めます。口座、金額、内部リスク、認証方式の詳細はサーバー側に保持します。

クライアントはトークンエンドポイントを直接呼び出してアップグレードできますか?

いいえ。認可サーバーでの認証と同意を通じてチャレンジに従う必要があります。トークン内で達成されたacrを主張するのはクライアントではなくサーバーです。

アップグレードされたトークンが別の送金に使用されるのをどのように防ぎますか?

対象者、リソース、チャレンジID、またはトランザクションダイジェストをワンタイムのサーバー状態にバインドし、送金に冪等性キーを使用します。

イントロスペクションが一時的に利用できない場合はどうしますか?

リソースのリスクによって分類します。短いキャッシュ証拠で通常の読み取りを処理できますが、コンテキストを確認できない場合、支払いと権限変更はフェイルクローズとします。

チャレンジを理解しない古いクライアントをどのようにサポートしますか?

ドキュメント化されたエラーとSDK移行ガイドを公開し、テナントごとに有効化します。高リスクな操作は、移行が完了するまでその要件を維持します。

公開情報ソース

関連する質問