OIDC / OAuth 2.0 の用語を 3 つの軸で整理する — Authorization Code / Implicit / Confidential / Public / PKCE

2026-08-28 16:02 (68 minutes ago)

OIDC と OAuth 2.0 の用語は、対立しているように見えて実は別の軸のものが多い。「Implicit の反対は Confidential だっけ?」のような混乱は、ここから来る。自分も自作の OIDC プロバイダーを作っているときに、頭の中がしばらく整理できていなかった。

軸を 3 本に分けて覚えると、ほぼ解消する。

対立する用語 何を決めるか
1. フロー Authorization Code ↔ Implicit ↔ Hybrid トークンをどこで受け取るか
2. クライアント種別 Confidential ↔ Public クレデンシャルを秘密に保てるか
3. クライアント認証方式 client_secret_basic / private_key_jwt / tls_client_auth / none token endpoint でどう本人証明するか

PKCE はこの 3 軸すべてと直交している。軸ではなく、軸をまたいで効く保護機構だ。

つまり Implicit の対義語は Authorization Code で、Confidential の対義語は Public。この 2 つは別の軸なので、直接対立しない。

軸 1: フロー — トークンをどこで受け取るか

response_type で決まる。

response_type 受け取り方 現状
code 引換券 (code) だけをリダイレクトで受け取り、バックチャネルで token endpoint に交換 PKCE と併せてこれ一択
id_token / id_token token (Implicit) トークンがフロントチャネル (URL fragment) に直接返る 非推奨
code id_token 等 (Hybrid) 両方 非推奨方向
[Authorization Code Flow]

ブラウザ ──① 認可リクエスト──▶ 認可サーバー
        ◀─② code (リダイレクト)──
アプリ ─────③ code + PKCE verifier ──▶ token endpoint   ← バックチャネル
     ◀────④ id_token / access_token ──

code は引換券であって、それ自体には何の情報も入っていない。中身は ④ で初めて手に入る。フロントチャネル (ブラウザ) をトークンが通らないのが要点だ。

Implicit がなぜ退場したか

トークンが URL fragment に載るため、ブラウザの履歴、Referer ヘッダ、リバースプロキシや CDN のアクセスログ、拡張機能や同一ページ上の他のスクリプト、これらすべてが漏洩経路になる。

さらに、フロントチャネルで返るトークンは発行相手を暗号的に紐付けられないため、攻撃者が横取りしたトークンを自分のセッションに注入する攻撃 (token injection) を防ぎにくい。

RFC 9700 (OAuth 2.0 Security Best Current Practice, 2025-01) が非推奨とし、OAuth 2.1 では削除された。

厳密には、RFC 9700 が名指しで否定しているのは response_type=token (access_token をフロントチャネルに出すもの) だ。response_type=id_token のみ + response_mode=form_post の構成は、id_token が API の bearer credential ではないぶん危険度が低く、古い構成では今も見かける。それでも新規に選ぶ理由はない。

軸 2: クライアント種別 — Confidential / Public

判定基準は RFC 6749 §2.1 にある。クレデンシャルの機密性を維持できるか、それだけだ。

client_secret
Confidential サーバサイド Web アプリ、バッチ、サーバ間連携 持てる。サーバ内に置ける
Public SPA、モバイルアプリ、デスクトップアプリ、CLI 持てない。配布物に埋めても逆アセンブルや DevTools で読まれる

「Public client は secret を持たないから危険」ではない。持てないという事実を正しく認めた上で設計されているのが public client であって、危険なのは「public client なのに secret を埋め込んで confidential のつもりでいる」構成のほうだ。

軸 3: クライアント認証方式

Confidential client が token endpoint で自分を証明する方法で、token_endpoint_auth_method として登録する。

方式 内容
client_secret_basic secret を Authorization ヘッダで送る。最も一般的
client_secret_post secret をリクエストボディで送る
private_key_jwt クライアントが秘密鍵で署名した JWT (client assertion) を送る。secret が線に乗らない
tls_client_auth mTLS のクライアント証明書で認証
none public client。クライアント認証をしない

private_key_jwttls_client_auth は、共有秘密をネットワークに流さないという点で client_secret_* より強い。金融系など高セキュリティ要件で要求される。

PKCE が座標系を変えた

昔はこういう連鎖で考えられていた。

SPA は public client → client_secret が無い → token endpoint でクライアント認証できない → code を交換できない → だから Implicit を使うしかない

この「Public だから Implicit」という誤った結びつきが、Implicit と Confidential を対立概念だと錯覚させる原因になっている。

PKCE (RFC 7636) がこの前提を壊した。

PKCE はリクエストごとに使い捨ての code_verifier を生成し、認可リクエストにはそのハッシュ (code_challenge) だけを送る。code を横取りしても、元の code_verifier を知らなければトークンに交換できない。

秘密の共有も鍵管理も発生しない (毎回使い捨て)。したがって client_secret が無い public client でも Authorization Code Flow が使える。

結果、現在の対応はこうなる。

Authorization Code + PKCE Implicit
Confidential client 推奨 使わない
Public client 推奨 使わない

「Public だから Implicit」はもう成立しない。

また PKCE は public client 限定の対策ではない。RFC 9700 は全クライアントに推奨し、OAuth 2.1 では必須とされている。confidential client でも、認可レスポンスの横取り経路は塞いでおく価値がある。

おまけ: 「JWT か authorization code か」も対立ではない

同じ種類の混同として多いのがこれだ。

id_token は必ず JWT で、OIDC Core が "The ID Token is represented as a JSON Web Token (JWT)" と定義している。例外はない。authorization code は、その JWT を安全に受け取るための手段だ。つまり二択ではなく両方を使う。code を交換した結果として JWT が返る。

一方で access_token のフォーマットは仕様上自由で、ここは本当に分岐がある。

検証方法 特徴
JWT (RFC 9068) ローカルで署名検証 速い。認可サーバーへの往復が不要。失効が効かない (期限まで有効)
opaque (ただの乱数文字列) Token Introspection (RFC 7662) で問い合わせ 即座に失効できる。毎回往復が発生する

「アクセストークンを JWT にすべきか」という議論はこちらの話であって、id_token には選択の余地がない。

ちなみに UserInfo エンドポイントのレスポンスは通常ただの JSON だ (署名や暗号化をしたい場合は JWT にもできる)。「OIDC は全部 JWT」というわけでもない。

参考

  • RFC 6749 §2.1 — Client Types (Confidential / Public)
  • RFC 7636 — PKCE
  • RFC 7662 — OAuth 2.0 Token Introspection
  • RFC 9068 — JWT Profile for OAuth 2.0 Access Tokens
  • RFC 9700 — OAuth 2.0 Security Best Current Practice
  • OpenID Connect Core 1.0 §3 (Authentication) / §2 (ID Token)
評価をお願いします (会員登録・ログイン不要)
まだ評価がありません
著者は、アプリケーション開発会社 Cyberneura を運営しています。
開発相談をお待ちしています。

アーカイブ