要約

  • RFC 10017 は、完全な BFF、Token 仲介バックエンド、ブラウザー OAuth クライアントの順に安全性が高いと整理する。完全な BFF は Access Token、Refresh Token、機密クライアント資格情報を JavaScript から隔離する。
  • その設計は Token 窃取と機密クライアントとしての新規 Token 取得を防ぐが、正規 Origin 内の悪意あるコードが利用者の Cookie セッションを使って BFF に命令することまでは防がない。
  • 必要なのは、Origin と実行コード、Cookie と CSRF、BFF の宛先・Path・Method、Resource Server の認可、不可逆操作の確認、セッション失効、最終結果の証跡を別々に管理することである。

人事システムの画面から、退職者の権限を停止する。画面の JavaScript は OAuth Token を持たない。ブラウザーにあるのは HttpOnly Cookie だけで、BFF がサーバー側の Token を取り出し、複数の業務 API に指示を送る。

ところが、同じ画面に読み込まれた依存ライブラリが改ざんされていた。そのコードは別の社員を対象にした停止命令も BFF に送る。Cookie はブラウザーが自動的に付ける。BFF は正規セッションとして受け入れ、Token を付けて転送する。Token は一度も漏れていない。それでも業務結果は誤った。

2026 年 8 月公開の IETF Best Current Practice、RFC 10017 が示す核心はここにある。BFF は攻撃者が持ち出せる資格情報を大幅に減らす。しかし、承認済み Origin から来たすべての命令を利用者の意思に変換する装置ではない。

悪意あるコードは Token 以外も利用する

RFC 10017 の脅威モデルでは、悪意ある JavaScript や WebAssembly がアプリケーションの実行環境に入った時点から考える。そのコードは正規コードと同じブラウザー権限を持つ。同一 Origin の画面や Storage に触れ、実行フローを書き換え、正規 Origin から Request を送れる。

文書は四つの攻撃を分ける。一回だけ現在の Token を盗む攻撃、更新されるたびに盗む永続的な攻撃、既存 Storage を無視して新しい Authorization Code Flow を起動する攻撃、そして Token を持ち出さず利用者のブラウザーから直接 Request を送る攻撃である。

この区別が防御の限界を決める。短寿命 Access Token は一回の窃取の時間を短くするが、常駐コードは次の Token を待てる。Refresh Token Rotation は再利用を検出できる場合があるが、攻撃者が常に最新版を取り、正規アプリに使わせなければ reuse は現れない。Web Worker は保存済み Token を隔離できても、Authorization Server に新しい Token を求める動作までは止めない。

PKCE は必須であり、横取りされた Authorization Code の交換を防ぐ。だが、登録済み Redirect Origin 内で動く悪意あるコードと正規コードの意思を区別しない。DPoP や非抽出鍵も、コピーした Token の外部利用を難しくする一方、同一 Origin のコードが新しい Flow を自分の鍵で始めたり、現在の署名機能を使ったりする危険を残す。

BFF が守るものと、BFF が引き受けるもの

完全な BFF では、サーバー側コンポーネントが OAuth の機密クライアントになる。Authorization Code と PKCE を使い、Access Token と Refresh Token を保管し、Cookie セッションに関連付け、Resource Server への全呼び出しを仲介する。ブラウザーコードには Token を返さない。

この構造は三つの経路を閉じる。ブラウザーに盗める Token がなく、永続コードも更新 Token を収集できない。悪意あるコードが Authorization Code を得ても、BFF の機密資格情報がなければ同じクライアントとして交換できない。HttpOnly はセッション識別子の直接読み取りも防ぐ。

残るのは In-Context の命令である。アプリケーションは BFF を呼べなければ機能しない。正規 Origin 内の悪意あるコードも同じ Endpoint を呼べる。ブラウザーが Cookie を付け、BFF がセッションを Token に翻訳するため、攻撃者は Token 境界を越える必要がない。

したがって BFF は汎用 Proxy であってはならない。RFC 10017 は、転送先 Host と Path を明示的に許可し、Endpoint ごとに Method を制限するよう求める。ブラウザーが送る URL をそのまま Token 付きで取得する設計は、Token Vault を Open Relay に変える。

Cookie にも独立した要件がある。SecureHttpOnly は必須、SameSite=Strict、Path /Domain を付けないこと、Host に結び付く Prefix が推奨される。ただし Cookie は自動送信されるため、状態変更 Endpoint には CSRF 対策が残る。JavaScript が Cookie を読めないことと、Cookie を使った命令を送れないことは同じではない。

BFF は機密資格情報、Token、Session、Routing を集約する。全トラフィックを観測できるので異常検知や Rate Limit に向く一方、容量、地域間整合性、失効、復旧の責任も集中する。

Token 仲介は長期権限を守り、短期権限を返す

Token 仲介バックエンドも機密クライアントであり、Refresh Token をサーバーに残す。しかし Access Token はブラウザーに渡し、フロントエンドが Resource Server を直接呼ぶ。全通信を Proxy する負担は減るが、公開した境界に危険が戻る。

悪意あるコードは Refresh Token を盗めず、機密クライアントとして新しい Flow を完了できない。それでも Access Token は盗める。隔離 Storage に置いても、現在の Session で仲介 Endpoint に新しい Access Token を要求できる場合がある。

DPoP の責任も分かれる。Token を取得するのはバックエンド、使用するのはブラウザーである。RFC 10017 はこの分割方式を定義していない。図に PoP と書くだけでは、鍵の保管者と Proof の生成者を証明できない。そのため文書は、完全な BFF が成立しない要件がある場合に限って仲介方式を検討するよう強く促す。

ブラウザーだけのクライアントは公開クライアントのまま

ブラウザーが OAuth Client になる方式では、Bundle に埋めた Secret を機密資格情報として扱えない。Authorization Code と PKCE、完全一致の Redirect URI、CSRF 対策が必要である。Refresh Token を発行するなら、毎回 Rotation するか Sender-Constrain し、最大寿命または未使用期限を設ける。

Origin は Scheme、Host、Port の組であり、ブラウザーの実際の権限境界になる。RFC 10017 は一つの Origin に一つのアプリケーションを推奨する。組織上は別製品でも Origin を共有すれば、ブラウザー上では広い能力を共有する。

CORS は Cross-Origin Response をコードに見せるかどうかを制御するもので、Resource Server の認可ではない。許可された Origin 内の正規コードと悪意あるコードも区別しない。postMessage も、送信側と受信側の Origin を厳密に検証して初めて境界になる。

Service Worker は Origin より上位の権限になれない

Service Worker に OAuth Flow と Token を置けば、隔離されたメモリーから Request に Token を追加できる。ブラウザー内 BFF のように見える。しかし RFC 10017 はこの方式を推奨しない。悪意あるコードは Worker を登録解除し、保護がない新しい Browsing Context を開いて別の Flow を開始できる。

隔離は本物でも、永続的な支配権ではない。Web Crypto の非抽出鍵も、API から鍵の値を読めないことを保証するにとどまり、TPM や暗号化された File System を必ず保証しない。さらに、誤ったコードが正しい環境に鍵の利用を依頼する問題は残る。

証跡は Vault ではなく結果までつなぐ

監査記録は、Application Origin と Script Release、依存関係と CSP の Fingerprint、プライバシーに配慮した Session Hash、CSRF 結果、BFF Route、転送先 Host/Path/Method、Token の Audience と Scope、Resource Policy、Object State、Idempotency Key、Commit Result を結び付けるべきである。生の Token、Cookie、Client Secret は記録しない。

負の試験も能力ごとに分ける。既存 Token を読めるか、更新を追跡できるか、新しい Flow を始められるか、仲介から Token を得られるか、Token を見ずに BFF を使えるか、転送先を変えられるか、応答喪失後に不可逆操作を二重実行できるか。OAuth 成功という一つの Boolean では説明できない。

Running-Code Primacy の基準では、BFF という名前に権限はない。実際の Cookie、Route、Token Vault、認可、失敗時動作だけが現実である。共通 OAuth 仕様は最小かつ決定的に保ち、業務結果の判断は損失を負う Service に残す。安全な Token という記号を、安全な命令へ膨張させてはならない。