この記事のポイント
- browser-based app は client secret を保持できない前提で設計する必要があります。
- PKCE は認可コードの横取り対策であり、SPA を confidential client に変える仕組みではありません。
- 権限の強い token exchange や秘密の保管は BFF や server-side に寄せる方が安全です。
まず無料で確認する
無料でASM診断を開始
クライアントシークレット 漏えいで触れている論点は、自社ドメインを実際に診断すると優先順位が掴みやすくなります。まずは外部公開資産を無料で可視化してください。
クライアントシークレット漏えいとは何か
client secret 漏えいの本質は、秘密を browser へ置いた瞬間に app type の前提が崩れ、権限の責任境界まで公開面へ近づくことにあります。
client secret は『文字列を隠す』より『保持できる主体を分ける』ことが重要です
クライアントシークレット漏えいとは、単に文字列がどこかへ流出した状態だけを指しません。OAuth や OIDC の文脈では、本来 secret を保持できる主体と、保持できない主体を取り違えること が問題の出発点です。browser-based app や single-page app は、配信物と通信が利用者端末へ届く時点で、秘密を保持できる前提を満たしません。つまり見えにくく埋め込んでいても、それは secret を守れている状態ではなく、最初から public client として扱うべき場所へ秘密を置いているだけです。
ここで重要なのは、client secret が漏れると認可の設定や token の扱いまで一緒に危うくなることです。たとえば browser から confidential client の前提で token を取得する構成は、秘密の露出だけでなく、redirect URI の管理、認可コード交換、refresh token の扱い、監査ログの責任分界まで曖昧にします。つまりクライアントシークレット漏えいは、文字列の管理ミスであると同時に、アプリケーション種別の誤設計でもあります。
既存の フロントエンドのAPIキー露出とは? が「browser に配る配信物へ秘密を載せる問題」を広く扱うのに対して、本記事は OAuth / OIDC 実装に絞り、public client と confidential client をどう誤用しやすいか を主役にします。API key 全般の話として処理してしまうと、なぜ client secret だけは app type の前提と直結するのかが見えにくくなります。
browser で見えない工夫は『秘匿できている』ことの証拠にはなりません
実装現場では、環境変数の prefix を変える、build 時に埋め込む、source map を消す、minify する、といった工夫で client secret を見えにくくしようとすることがあります。しかし browser-based app の secret 問題では、それらは本質的な対策ではありません。配信物、通信、開発者ツール、ブラウザ拡張機能、ログ、エラーメッセージを通じて、値は複製可能です。つまり browser に届く時点で、秘密として扱う前提が崩れていると考えるべきです。
とくに LLM で雛形を作ると、OIDC provider の設定値や sample code をそのまま front 側へ載せてしまうことがあります。これは「試しに動かした」段階では目立たなくても、本番化するとそのまま production architecture になります。秘密が文字として見えるかどうかではなく、誰の支配下にある runtime へ渡ったか を 기준に判断しないと、同じ誤りを繰り返します。
なぜ SPA や browser-based app で起きやすいのか
SPA は便利ですが、confidential client の前提を満たしません
IETF の browser-based apps guidance が強調しているのは、browser-based app は利用者端末上で動き、配信物や network traffic を利用者が観測できるため、confidential client として扱ってはならない という点です。ここを誤ると、「SPA なのに client secret を持つ」「token endpoint を browser から confidential client 扱いで呼ぶ」といった設計が生まれます。
SPA で事故が起きやすい理由は、画面実装のスピードが速く、認証の責任境界が後回しになりやすいからです。sample code や framework の quickstart では、まずログインして画面が動くことが優先されます。その結果、public client であるはずの front-end に、confidential client の前提を持ち込んでしまうことがあります。つまり問題は OAuth 自体ではなく、実装都合で app type の境界を曖昧にすることです。
既存の OAuth同意フィッシングとは? や デバイスコードフィッシングとは? は正規認可フローの悪用を主役にしていますが、本記事の論点は攻撃者が consent を奪うことではありません。開発者自身が SPA を confidential client のように扱うと、攻撃を待たずに境界が崩れている状態 になるところが問題です。
PKCE は重要ですが、secret を browser へ置いてよい理由にはなりません
PKCE は Proof Key for Code Exchange の略で、認可コードを途中で奪われても、そのまま token へ交換されにくくする仕組みです。これは browser-based app でも非常に重要です。しかし PKCE の役割は、認可コードの横取り対策であって、SPA を confidential client に変えることではありません。ここを誤解すると、PKCE を入れたから client secret を front に置いてよい という危険な判断につながります。
Auth0 などの app type 解説でも、public client と confidential client の違いは「どこで動くか」「秘密を保持できるか」にあります。つまり PKCE の有無より先に、アプリケーションがどの runtime で動き、秘密を安全に持てるかを見なければなりません。PKCE は public client を安全に運用する重要な補強ですが、public client のままである事実 は変わりません。
browser-based app は secret を保持できない前提で扱う
配信物や通信を通じて第三者が再取得できるため、client secret の秘匿条件を満たせません。
PKCE を使っても public client のままという前提を崩さない
PKCE は認可コードの横取り対策であり、browser に秘密を置けるようにする仕組みではありません。
権限の強い token exchange は BFF や server-side に寄せる
client secret を browser へ渡すより、責任境界を server 側へ戻した方が安全です。
redirect URI、allowed origin、secret rotation を一緒に管理する
秘密の置き場所だけでなく、認可設定や切り替え手順まで含めて初めて再発防止になります。
public client と confidential client をどう見分けるべきか
判定の軸は『どこで動くか』『誰が runtime を支配するか』です
public client と confidential client を分けるとき、よく「社内向けかどうか」「ログインがあるかどうか」「secret を見えにくく埋め込んでいるか」で考えてしまいます。しかし本質的な軸は、runtime を誰が支配しているか です。利用者端末上で実行され、配信物や通信が観測できるなら、それは browser-based app であり public client とみなすべきです。server-side で動き、秘密を運用管理下で保持できるなら confidential client を検討できます。
この判定を誤ると、client secret を front-end に置くだけでなく、refresh token の長寿命運用、server-to-server 想定の token exchange、広すぎる scope の front-channel 利用まで起きやすくなります。つまり client type の見極めは認証の設定値だけでなく、どの権限をどの経路で扱うか を決める基礎です。
『社内だけ』『PoC だけ』という理由では confidential client になりません
よくある誤解は、「社内利用だから browser に secret を置いても問題ない」「PoC だから一旦 front に持たせる」という判断です。しかし利用者が限定されていても、browser に届いた時点で secret は複製可能です。PoC でも本番でも、browser-based app が confidential client になるわけではありません。違うのは露出の期間や規模だけで、前提自体は同じです。
むしろ PoC ほど境界が曖昧なまま本番へ近づきやすく、後から BFF や proxy を入れ直すコストが大きくなります。だから実務では、PoC でも「front で公開してよい値」「server 側へ寄せる処理」「token exchange の責任者」を先に決めた方が、結果的に速く安全です。ここを曖昧にしたまま進めると、あとで秘密を隠すために構成全体を作り直す ことになります。
また、OpenID Connect や OAuth の設定画面で「web」や「single-page application」のテンプレートを選べるからといって、安全な設計が自動で完成するわけではありません。provider 側の選択肢は出発点に過ぎず、実際には redirect URI、token 保持場所、cookie 設計、proxy の有無、scope の絞り方を実装側で固める必要があります。つまり client type の判断は、console 画面の選択ではなく、運用を含めた設計判断です。
PKCE と BFF をどう使い分けるべきか
PKCE は public client の安全性を補い、BFF は秘密と高権限処理を server 側へ戻します
browser-based app では PKCE を使い、認可コードの横取りに備えるべきです。一方で、client secret や高権限 token の管理、token exchange、外部 API への代理実行は BFF や server-side に寄せた方が安全です。つまり PKCE と BFF は対立する選択肢ではなく、public client の認可と confidential client 的な秘密管理を分担する組み合わせです。
BFF は Backend for Frontend の略で、front-end 専用の server-side 境界を置き、browser から直接 third-party token や secret を扱わない構成です。これにより、secret の保管、refresh token の管理、利用量制限、監査ログ、異常検知、rotation を一か所で扱えます。front-end には画面表示に必要な最小限の情報だけを返し、権限の強い処理は browser の外へ出すのが基本です。
ただし BFF を置いたから終わりではありません。redirect URI の管理、CSRF 対策、session cookie の設計、token の audience 制御、server 側 API への過剰権限集中を一緒に見直さないと、秘密の置き場所を移しただけで別の弱点が残ります。だから PKCE / BFF の使い分けでは、「何を browser に残し、何を server 側へ戻すか」を文章で固定することが重要です。
実務では、公開 front-end から直接 token endpoint へ confidential client として接続しない、client secret は server 側の secrets manager や実行環境に限定する、front-end には state や code verifier など短命で役割が限定された値だけを置く、といった運用にすると整理しやすくなります。ここまで決めておくと、実装者が変わっても secret placement の基準がぶれにくくなります。
漏えい後は secret の失効だけでなく、公開面と認可設定を同時に見直します
client secret の漏えいが疑われたら、まず失効と再発行を行うのは当然です。しかしそれだけでは十分ではありません。browser bundle、公開 repo、古い staging、sample page、ログ、エラーメッセージ、debug endpoint に secret が残っていないかを調べ、さらに redirect URI、allowed origin、scope、token lifetime、refresh token の保持場所まで確認する必要があります。つまり初動では、秘密そのものと、その秘密を使える公開面 を同時に切り分けるべきです。
既存の セッショントークン窃取とは? が示すように、credential や token の事故は値の回収だけでなく、到達経路の確認が重要です。client secret でも同じで、「どこに置かれていたか」「誰が取得できたか」「どの token exchange に使えたか」を確認しないと、同じ構造で再発します。だから対応は rotation だけでなく、認可フローの再設計と公開面の縮小 まで含めて考える必要があります。
browser で完結してよい処理と server 側へ寄せる処理を分ける
閲覧、表示、軽い検索と、代理実行、管理操作、機密データ取得、長期 token 管理を同列に扱わず、責任境界を先に決めます。
責任境界表public client / confidential client の前提を実装単位で書き出す
SPA、mobile、backend、server-to-server を分類し、どこが secret を持てるか、どこが PKCE 前提かを明文化します。
app type 一覧BFF と PKCE を組み合わせて token 取得の責任を分ける
browser には短命の front-channel 情報だけを置き、client secret や token exchange は server 側へ集約します。
認証フロー図secret rotation と公開面の棚卸しを同時に回す
bundle、staging、公開 docs、sample page、public repo を一緒に見直し、秘密が残る面を消していきます。
再発防止運用ASM診断 PROで公開面の見直しを始めるなら

ASM診断 PRO は browser-based app と BFF の境界で見落としやすい host、staging、公開 docs、API 接点を棚卸しする入口として使いやすい構成です。
ASM診断 PRO は OAuth provider の設定を直接検査する製品でも、client secret を vault で保管する製品でもありません。それでも役立つのは、秘密を front-end に置く構造と一緒に増えがちな公開面 を外から整理できるからです。実際の実装ミスでは、browser bundle だけでなく、認証用の古い subdomain、検証用 redirect ページ、debug API、staging の login 導線、sample page が残っていることが多く、そこから secret placement の誤りが再発します。
とくに client secret の問題は、認可設定の画面だけを見ていても見落としがちです。外から見える host、認証導線、API endpoint、公開 docs を整理すると、「この front-end は本当に public client として閉じているか」「BFF を置いたつもりで古い front-channel が残っていないか」「sample page が本番 secret と同じ設定を参照していないか」を確認しやすくなります。つまり価値は、secret の保管場所と公開面の管理をつなげること にあります。
既存の フロントエンドのAPIキー露出とは?、公開リポジトリの情報漏えいとは?、シャドーAPIとは? と合わせて見ると、code、bundle、公開 API、古い redirect 面、staging のどこに秘密と認可境界のズレが残っているかを横断して点検できます。OAuth 実装の見直しを運用へ落とすなら、まずは 外から見える認証接点と API 接点を棚卸しすること から始めてください。
次のアクション
client secret の見直しに向けて、まず公開されている認証接点を棚卸ししてください
無料で外部公開資産を診断し、認証用 subdomain、staging、公開 docs、API endpoint を洗い出して、browser-based app と BFF の境界が実際にどう見えているかを整理する起点を作れます。
よくある質問(FAQ)
SPA に client secret を置いても、難読化すれば安全ですか
安全ではありません。browser へ届いた時点で配信物と通信は複製可能であり、難読化は秘匿条件を満たす仕組みではありません。
PKCE を使っていれば confidential client と同じように扱えますか
扱えません。PKCE は認可コード横取りの対策であり、browser-based app に secret を保持させる根拠にはなりません。
client_id も browser に置いてはいけませんか
client_id は識別子であり、client secret と同じ秘匿性は前提にされません。問題は、その client_id がどの redirect 設定や権限と結びついているかです。
BFF を入れると必ず安全になりますか
必ずではありません。BFF 自体の session、CSRF、token 管理、最小権限設計まで見直して初めて効果が出ます。
漏えいが疑われたら最初に何を見るべきですか
secret の失効だけでなく、bundle、staging、public repo、redirect URI、token exchange の経路を同時に見て、再発面を潰してください。
まとめ
クライアントシークレット漏えいの本質は、秘密の保管ミスだけでなく、browser-based app と confidential client の境界を曖昧にしたことにあります。
クライアントシークレット漏えいは、secret が見えたかどうかだけで評価する問題ではありません。public client として扱うべき browser-based app に confidential client の前提を持ち込むと、秘密の露出、redirect 設定の誤用、token exchange の責任境界、refresh token 管理のすべてが崩れます。したがって本質は「文字列の管理」ではなく、どの app type がどの権限を持つべきかを設計で固定できているか にあります。
実務では、まず browser へ配る front-end が public client であることを明確にし、PKCE を使って認可コードの保護を行いながら、client secret と高権限 token 管理は BFF や server-side へ戻してください。そのうえで redirect URI、allowed origin、scope、token lifetime、rotation、監査ログを一緒に設計すると、秘密の置き場所だけでなく認証フロー全体の安全性が上がります。つまり対策は、front-end を楽に動かすための近道を、責任境界に沿った構成へ戻すこと です。
さらに再発防止では、secret の失効だけで終わらせず、公開 bundle、staging、sample page、redirect 導線、公開 API、repo 露出まで横断して確認する必要があります。OAuth 実装の問題は設定画面の中だけでは完結せず、外から見える接点とセットで残り続けるからです。client secret を browser に置かないという原則を、実装・運用・公開面の三つで守れるようになると、OAuth / OIDC を使う front-end でも速度と安全性を両立しやすくなります。
次のアクション
読み終えたら、無料でASM診断を開始
外部公開資産の現状を無料で確認し、管理漏れや優先して見るべきリスクを洗い出してください。記事で読んだ内容を、そのまま自社の判断へつなげやすくなります。
参考にした一次ソース
重要論点の根拠として参照した一次ソースだけを掲載しています。
browser-based app が confidential client ではなく public client として扱われる理由、BFF や token mediator の考え方を整理するために参照しました。
public client と confidential client の違い、SPA と regular web application の扱いを整理するために参照しました。
client secret を browser へ持たせない認証設計と、server-side で扱うべき責任境界を確認するために参照しました。
front-end 実装で起きやすい confidential client 誤用と、BFF / PKCE の役割整理を補強するために参照しました。