この記事のポイント
- ブラウザ実行アプリはクライアントシークレットを保持できない前提で設計する必要があります。
- PKCE は認可コードの横取り対策であり、SPA を機密クライアントに変える仕組みではありません。
- 権限の強いトークン交換や秘密の保管は BFF やサーバー側に寄せる方が安全です。
まず無料で確認する
無料でASM診断を開始
クライアントシークレット 漏えいで触れている論点は、自社ドメインを実際に診断すると優先順位が掴みやすくなります。まずは外部公開資産を無料で可視化してください。
クライアントシークレット漏えいとは何か

クライアントシークレット漏えいの本質は、秘密をブラウザへ置いた瞬間にアプリ種別の前提が崩れ、権限の責任境界まで公開面へ近づくことにあります。
クライアントシークレットは『文字列を隠す』より『保持できる主体を分ける』ことが重要です
クライアントシークレット漏えいとは、単に文字列がどこかへ流出した状態だけを指しません。OAuth や OIDC の文脈では、本来秘密を保持できる主体と、保持できない主体を取り違えることが問題の出発点です。ブラウザ実行アプリや単一ページアプリは、配信物と通信が利用者端末へ届く時点で、秘密を保持できる前提を満たしません。つまり見えにくく埋め込んでいても、それは秘密を守れている状態ではなく、最初から公開クライアントとして扱うべき場所へ秘密を置いているだけです。
ここで重要なのは、クライアントシークレットが漏れると認可の設定やトークンの扱いまで一緒に危うくなることです。たとえばブラウザから機密クライアントの前提でトークンを取得する構成は、秘密の露出だけでなく、リダイレクト URI の管理、認可コード交換、更新用トークンの扱い、監査ログの責任分界まで曖昧にします。つまりクライアントシークレット漏えいは、文字列の管理ミスであると同時に、アプリケーション種別の誤設計でもあります。
既存の フロントエンドのAPIキー露出とは? が「ブラウザに配る配信物へ秘密を載せる問題」を広く扱うのに対して、本記事は OAuth / OIDC 実装に絞り、公開クライアントと機密クライアントをどう誤用しやすいかを主役にします。API キー全般の話として処理してしまうと、なぜクライアントシークレットだけはアプリ種別の前提と直結するのかが見えにくくなります。
ブラウザで見えない工夫は『秘匿できている』ことの証拠にはなりません
実装現場では、環境変数の接頭辞を変える、ビルド時に埋め込む、ソースマップを消す、難読化する、といった工夫でクライアントシークレットを見えにくくしようとすることがあります。しかしブラウザ実行アプリの秘密問題では、それらは本質的な対策ではありません。配信物、通信、開発者ツール、ブラウザ拡張機能、ログ、エラーメッセージを通じて、値は複製可能です。つまりブラウザに届く時点で、秘密として扱う前提が崩れていると考えるべきです。
とくに LLM で雛形を作ると、OIDC 提供側の設定値やサンプルコードをそのままフロント側へ載せてしまうことがあります。これは「試しに動かした」段階では目立たなくても、本番化するとそのまま本番構成になります。秘密が文字として見えるかどうかではなく、誰の支配下にある実行環境へ渡ったかを基準に判断しないと、同じ誤りを繰り返します。
なぜ SPA やブラウザ実行アプリで起きやすいのか
SPA は便利ですが、機密クライアントの前提を満たしません
IETF のブラウザ向け OAuth ガイダンスが強調しているのは、ブラウザ実行アプリは利用者端末上で動き、配信物や通信を利用者が観測できるため、機密クライアントとして扱ってはならないという点です。ここを誤ると、「SPA なのにクライアントシークレットを持つ」「トークンエンドポイントをブラウザから機密クライアント扱いで呼ぶ」といった設計が生まれます。
SPA で事故が起きやすい理由は、画面実装のスピードが速く、認証の責任境界が後回しになりやすいからです。サンプルコードやフレームワークのクイックスタートでは、まずログインして画面が動くことが優先されます。その結果、公開クライアントであるはずのフロントエンドに、機密クライアントの前提を持ち込んでしまうことがあります。つまり問題は OAuth 自体ではなく、実装都合でアプリ種別の境界を曖昧にすることです。
既存の OAuth同意フィッシングとは? や デバイスコードフィッシングとは? は正規認可フローの悪用を主役にしていますが、本記事の論点は攻撃者が同意を奪うことではありません。開発者自身が SPA を機密クライアントのように扱うと、攻撃を待たずに境界が崩れている状態になるところが問題です。
PKCE は重要ですが、秘密をブラウザへ置いてよい理由にはなりません
PKCE は認可コードを途中で奪われても、そのままトークンへ交換されにくくする仕組みです。これはブラウザ実行アプリでも非常に重要です。しかし PKCE の役割は、認可コードの横取り対策であって、SPA を機密クライアントに変えることではありません。ここを誤解すると、PKCE を入れたからクライアントシークレットをフロントに置いてよいという危険な判断につながります。
Auth0 などのアプリ種別解説でも、公開クライアントと機密クライアントの違いは「どこで動くか」「秘密を保持できるか」にあります。つまり PKCE の有無より先に、アプリケーションがどの実行環境で動き、秘密を安全に持てるかを見なければなりません。PKCE は公開クライアントを安全に運用する重要な補強ですが、公開クライアントのままである事実は変わりません。
ブラウザ実行アプリは秘密を保持できない前提で扱う
配信物や通信を通じて第三者が再取得できるため、クライアントシークレットの秘匿条件を満たせません。
PKCE を使っても公開クライアントのままという前提を崩さない
PKCE は認可コードの横取り対策であり、ブラウザに秘密を置けるようにする仕組みではありません。
権限の強いトークン交換は BFF やサーバー側に寄せる
クライアントシークレットをブラウザへ渡すより、責任境界をサーバー側へ戻した方が安全です。
リダイレクト URI、許可済みオリジン、秘密の更新を一緒に管理する
秘密の置き場所だけでなく、認可設定や切り替え手順まで含めて初めて再発防止になります。
公開クライアントと機密クライアントをどう見分けるべきか
判定の軸は『どこで動くか』『誰が実行環境を支配するか』です
公開クライアントと機密クライアントを分けるとき、よく「社内向けかどうか」「ログインがあるかどうか」「秘密を見えにくく埋め込んでいるか」で考えてしまいます。しかし本質的な軸は、実行環境を誰が支配しているかです。利用者端末上で実行され、配信物や通信が観測できるなら、それはブラウザ実行アプリであり公開クライアントとみなすべきです。サーバー側で動き、秘密を運用管理下で保持できるなら機密クライアントを検討できます。
この判定を誤ると、クライアントシークレットをフロントエンドに置くだけでなく、更新用トークンの長寿命運用、サーバー間連携を想定したトークン交換、広すぎる権限範囲のフロントチャネル利用まで起きやすくなります。つまりクライアント種別の見極めは認証の設定値だけでなく、どの権限をどの経路で扱うかを決める基礎です。
『社内だけ』『PoC だけ』という理由では機密クライアントになりません
よくある誤解は、「社内利用だからブラウザに秘密を置いても問題ない」「PoC だから一旦フロントに持たせる」という判断です。しかし利用者が限定されていても、ブラウザに届いた時点で秘密は複製可能です。PoC でも本番でも、ブラウザ実行アプリが機密クライアントになるわけではありません。違うのは露出の期間や規模だけで、前提自体は同じです。
むしろ PoC ほど境界が曖昧なまま本番へ近づきやすく、後から BFF や中継サーバーを入れ直すコストが大きくなります。だから実務では、PoC でも「フロントで公開してよい値」「サーバー側へ寄せる処理」「トークン交換の責任者」を先に決めた方が、結果的に速く安全です。ここを曖昧にしたまま進めると、あとで秘密を隠すために構成全体を作り直すことになります。
また、OpenID Connect や OAuth の設定画面で「Web」や「単一ページアプリ」のテンプレートを選べるからといって、安全な設計が自動で完成するわけではありません。提供側の選択肢は出発点に過ぎず、実際にはリダイレクト URI、トークン保持場所、Cookie 設計、中継サーバーの有無、権限範囲の絞り方を実装側で固める必要があります。つまりクライアント種別の判断は、管理画面の選択ではなく、運用を含めた設計判断です。
PKCE と BFF をどう使い分けるべきか
PKCE は公開クライアントの安全性を補い、BFF は秘密と高権限処理をサーバー側へ戻します
ブラウザ実行アプリでは PKCE を使い、認可コードの横取りに備えるべきです。一方で、クライアントシークレットや高権限トークンの管理、トークン交換、外部 API への代理実行は BFF やサーバー側に寄せた方が安全です。つまり PKCE と BFF は対立する選択肢ではなく、公開クライアントの認可と機密クライアント的な秘密管理を分担する組み合わせです。
BFF はフロントエンド専用のサーバー側境界を置き、ブラウザから直接外部サービスのトークンや秘密を扱わない構成です。これにより、秘密の保管、更新用トークンの管理、利用量制限、監査ログ、異常検知、秘密の更新を一か所で扱えます。フロントエンドには画面表示に必要な最小限の情報だけを返し、権限の強い処理はブラウザの外へ出すのが基本です。
ただし BFF を置いたから終わりではありません。リダイレクト URI の管理、CSRF 対策、セッション Cookie の設計、トークンの対象制御、サーバー側 API への過剰権限集中を一緒に見直さないと、秘密の置き場所を移しただけで別の弱点が残ります。だから PKCE / BFF の使い分けでは、「何をブラウザに残し、何をサーバー側へ戻すか」を文章で固定することが重要です。
実務では、公開フロントエンドから直接トークンエンドポイントへ機密クライアントとして接続しない、クライアントシークレットはサーバー側の秘密保管基盤や実行環境に限定する、フロントエンドには state や code verifier など短命で役割が限定された値だけを置く、といった運用にすると整理しやすくなります。ここまで決めておくと、実装者が変わっても秘密の置き場所の基準がぶれにくくなります。
あわせて、認証基盤の管理画面で登録したアプリ種別と、実際のフロントエンド実装が一致しているかを定期的に照合する運用も重要です。設定画面では Web アプリとして登録されていても、実装側では静的配信の単一ページアプリとして動いていることがあります。この差分を放置すると、管理画面上は機密クライアント、実態は公開クライアントという最も危うい状態が続きます。
そのためレビューでは、フロントエンドの実装だけでなく、認可サーバー側の登録内容、許可済みオリジン、リダイレクト URI、トークン交換の実行主体を一枚の図に戻して確認した方が安全です。秘密の保管場所を局所的に直すより、認証フロー全体の責任境界を見直す方が再発防止として効きます。
また、認可サーバー側の設定差分を pull request や変更申請へ残しておくと、「いつ公開クライアント相当の実装へ寄ってしまったか」を後から追いやすくなります。実装と設定を別チームで持つ場合ほど、設定差分の監査線を用意した方が事故後の切り分けが早くなります。設定変更の承認者まで残しておくと、再発防止の責任分担も明確になります。変更理由も残すとさらに有効です。
漏えい後の初動と再発防止をどう進めるか
失効と再発行だけで終わらせず、どこまで到達されたかを切り分けます
クライアントシークレットの漏えいが疑われたら、まず失効と再発行を行うのは当然です。しかしそれだけでは十分ではありません。重要なのは、その秘密がどの認可設定、どのトークン交換、どの API 呼び出しに結び付いていたかを切り分けることです。秘密が見えた経路と、秘密が使えた経路を分けて確認すると、影響範囲を絞りやすくなります。
GitHub の漏えいした秘密情報 remediation ガイドでも、値を止めるだけでなく、利用箇所、公開範囲、再設定手順を一緒に整理することが重要だと示されています。OAuth 実装でも同様で、失効したあとに認可設定の棚卸しまで進めないと、同じ場所へ新しい秘密を入れ直して再発することがあります。
公開配信物、検証環境、古いリダイレクト面を横断して消し込みます
実務では、漏えいした秘密がどこに残っているかを横断して確認する必要があります。公開配信物、検証環境、サンプルページ、古いリダイレクト URL、公開ドキュメント、リポジトリ、ビルドログを一つずつ見直すと、値そのものが消えても参照先や誤った前提が残っていないかを確認できます。
特にブラウザ実行アプリでは、フロントのコードを直したつもりでも、古い検証環境や説明用ページに同じ設定が残っていることがあります。再発防止では「今の本番だけ直した」で止めず、公開されている認証接点と過去の配信面まで含めて掃除する方が安全です。
既存の セッショントークン窃取とは? が示すように、認証情報やトークンの事故は値の回収だけでなく、到達経路の確認が重要です。クライアントシークレットでも同じで、「どこに置かれていたか」「誰が取得できたか」「どのトークン交換に使えたか」を確認しないと、同じ構造で再発します。だから対応は秘密の更新だけでなく、認可フローの再設計と公開面の縮小まで含めて考える必要があります。
再発防止は設計標準とレビュー観点へ戻して初めて完了します
漏えい後の作業を確実に閉じるには、暫定対応を設計標準へ戻す必要があります。具体的には、フロントエンドが保持してよい値、BFF を必須にする条件、リダイレクト URI の登録手順、秘密の更新手順、検証環境の閉鎖条件を設計書へ書き戻します。事故対応を設計標準へ戻さないと、次の案件で同じ近道が再登場します。
さらに、コードレビューでも「秘密文字列が見えるか」だけではなく、「この処理は公開クライアントで完結してよいか」「BFF を置くべき責任が残っていないか」「公開ドキュメントやサンプルページへ誤った設定が残っていないか」を確認項目に入れる方が再発しにくくなります。クライアントシークレット漏えいは、単一の設定ミスというより、認証境界のレビュー不足が複数箇所に現れた結果として起きやすいからです。
ブラウザで完結してよい処理とサーバー側へ寄せる処理を分ける
閲覧、表示、軽い検索と、代理実行、管理操作、機密データ取得、長期トークン管理を同列に扱わず、責任境界を先に決めます。
責任境界表公開クライアント / 機密クライアントの前提を実装単位で書き出す
SPA、モバイル、バックエンド、サーバー間連携を分類し、どこが秘密を持てるか、どこが PKCE 前提かを明文化します。
アプリ種別一覧BFF と PKCE を組み合わせてトークン取得の責任を分ける
ブラウザには短命のフロントチャネル情報だけを置き、クライアントシークレットやトークン交換はサーバー側へ集約します。
認証フロー図秘密の更新と公開面の棚卸しを同時に回す
配信バンドル、検証環境、公開ドキュメント、サンプルページ、公開リポジトリを一緒に見直し、秘密が残る面を消していきます。
再発防止運用ASM診断 PROで公開面の見直しを始めるなら

ASM診断 PRO はブラウザ実行アプリと BFF の境界で見落としやすいホスト、検証環境、公開ドキュメント、API 接点を棚卸しする入口として使いやすい構成です。
ASM診断 PRO は OAuth 提供側の設定を直接検査する製品でも、クライアントシークレットを保管庫で管理する製品でもありません。それでも役立つのは、秘密をフロントエンドに置く構造と一緒に増えがちな公開面を外から整理できるからです。実際の実装ミスでは、配信バンドルだけでなく、認証用の古いサブドメイン、検証用のリダイレクトページ、デバッグ用 API、検証環境のログイン導線、サンプルページが残っていることが多く、そこから秘密の置き場所の誤りが再発します。
とくにクライアントシークレットの問題は、認可設定の画面だけを見ていても見落としがちです。外から見えるホスト、認証導線、API 接点、公開ドキュメントを整理すると、「このフロントエンドは本当に公開クライアントとして閉じているか」「BFF を置いたつもりで古いフロントチャネルが残っていないか」「サンプルページが本番秘密と同じ設定を参照していないか」を確認しやすくなります。つまり価値は、秘密の保管場所と公開面の管理をつなげることにあります。
既存の フロントエンドのAPIキー露出とは?、公開リポジトリの情報漏えいとは?、シャドーAPIとは? と合わせて見ると、コード、配信バンドル、公開 API、古いリダイレクト面、検証環境のどこに秘密と認可境界のズレが残っているかを横断して点検できます。OAuth 実装の見直しを運用へ落とすなら、まずは 外から見える認証接点と API 接点を棚卸しすることから始めてください。
次のアクション
クライアントシークレットの見直しに向けて、まず公開されている認証接点を棚卸ししてください
無料で外部公開資産を診断し、認証用サブドメイン、検証環境、公開ドキュメント、API 接点を洗い出して、ブラウザ実行アプリと BFF の境界が実際にどう見えているかを整理する起点を作れます。
よくある質問(FAQ)
SPA にクライアントシークレットを置いても、難読化すれば安全ですか
安全ではありません。ブラウザへ届いた時点で配信物と通信は複製可能であり、難読化は秘匿条件を満たす仕組みではありません。
PKCE を使っていれば機密クライアントと同じように扱えますか
扱えません。PKCE は認可コード横取りの対策であり、ブラウザ実行アプリに秘密を保持させる根拠にはなりません。
クライアント ID もブラウザに置いてはいけませんか
client_id は識別子であり、クライアントシークレットと同じ秘匿性は前提にされません。問題は、その client_id がどのリダイレクト設定や権限と結びついているかです。
BFF を入れると必ず安全になりますか
必ずではありません。BFF 自体のセッション、CSRF、トークン管理、最小権限設計まで見直して初めて効果が出ます。
漏えいが疑われたら最初に何を見るべきですか
秘密の失効だけでなく、配信バンドル、検証環境、公開リポジトリ、リダイレクト URI、トークン交換の経路を同時に見て、再発面を潰してください。
まとめ

クライアントシークレット漏えいの本質は、秘密の保管ミスだけでなく、ブラウザ実行アプリと機密クライアントの境界を曖昧にしたことにあります。
クライアントシークレット漏えいは、秘密が見えたかどうかだけで評価する問題ではありません。公開クライアントとして扱うべきブラウザ実行アプリに機密クライアントの前提を持ち込むと、秘密の露出、リダイレクト設定の誤用、トークン交換の責任境界、更新用トークン管理のすべてが崩れます。したがって本質は「文字列の管理」ではなく、どのアプリ種別がどの権限を持つべきかを設計で固定できているかにあります。
実務では、まずブラウザへ配るフロントエンドが公開クライアントであることを明確にし、PKCE を使って認可コードの保護を行いながら、クライアントシークレットと高権限トークン管理は BFF やサーバー側へ戻してください。そのうえでリダイレクト URI、許可済みオリジン、権限範囲、トークンの有効期間、秘密の更新、監査ログを一緒に設計すると、秘密の置き場所だけでなく認証フロー全体の安全性が上がります。つまり対策は、フロントエンドを楽に動かすための近道を、責任境界に沿った構成へ戻すことです。
さらに再発防止では、秘密の失効だけで終わらせず、公開バンドル、検証環境、サンプルページ、リダイレクト導線、公開 API、リポジトリ露出まで横断して確認する必要があります。OAuth 実装の問題は設定画面の中だけでは完結せず、外から見える接点とセットで残り続けるからです。クライアントシークレットをブラウザに置かないという原則を、実装・運用・公開面の三つで守れるようになると、OAuth / OIDC を使うフロントエンドでも速度と安全性を両立しやすくなります。
次のアクション
読み終えたら、無料でASM診断を開始
外部公開資産の現状を無料で確認し、管理漏れや優先して見るべきリスクを洗い出してください。記事で読んだ内容を、そのまま自社の判断へつなげやすくなります。
参考にした一次ソース
重要論点の根拠として参照した一次ソースだけを掲載しています。
ブラウザ実行アプリが機密クライアントではなく公開クライアントとして扱われる理由と、BFF を含む構成の考え方を整理するために参照しました。
公開クライアントと機密クライアントの違い、SPA と通常の Web アプリの扱いを整理するために参照しました。
OAuth 実装で避けるべき構成と、秘密情報やトークンの扱いをどう安全側へ寄せるべきかを補強するために参照しました。
漏えい後の初動で、秘密の失効だけでなく利用箇所と再発防止をどう一緒に整理するかを補強するために参照しました。