OAuth/OIDCフローの選び方全比較

Authorization Code、PKCE、Client Credentials、Device Authorization、Implicit、Resource Owner Password の6つのフローを比較。判断フローチャートと PKCE の仕組みをわかりやすく解説。

はじめに

OAuth 2.0 / OIDC には複数の認証フローがあり、「どれを使えばいいのか」が最初の壁になります。この記事では、各フローの動き・用途・セキュリティ特性を整理し、判断フローチャートで選び方を示します。

フロー一覧

フロー一言で使う場面ステータス
Authorization Code一番安全、基本これサーバーサイドのある Web アプリ推奨
Authorization Code + PKCE↑の Public クライアント版SPA、モバイル、CLI推奨
Client Credentialsユーザー不在、マシン間通信バックエンド同士の API 呼び出し推奨
Device Authorization画面入力できないデバイステレビ、CLI、IoT推奨
Implicitトークン直接返却昔の SPA非推奨
Resource Owner Passwordパスワード直送レガシー移行の一時しのぎ非推奨

各フローの動き

Authorization Code

サーバーサイドのある Web アプリ向け。最も一般的で最も安全。

バックエンドOIDC Provider (auth.example.com)ブラウザバックエンドOIDC Provider (auth.example.com)ブラウザセッション確立ログインボタン押下1ログイン画面 → 認証2認可コード発行(redirect_uri に戻る)3認可コードをバックエンドに渡す4認可コード + client_secret → トークン交換(サーバー間通信)5トークン取得6

Authorization Code + PKCE

SPA やモバイルアプリなど、client_secret を安全に保持できないクライアント向け。

OIDC Providerブラウザ / モバイルOIDC Providerブラウザ / モバイルopt[一致すれば]code_verifier(ランダム値)を生成、code_challenge = SHA256(code_verifier)1認可リクエスト(code_challenge 付き)2code_challenge を保存、認可コード発行3トークン交換(code_verifier 付き)4SHA256(code_verifier) == 保存した code_challenge ?5トークン発行6

client_secret の代わりに PKCE で「認可コードを要求した人 = トークン交換する人」を証明します。

Client Credentials

ユーザーが介在しない、サービス間通信向け。

バックエンド BOIDC Providerバックエンド Aバックエンド BOIDC Providerバックエンド Aclient_id + client_secret で直接トークン要求1トークン発行(sub はサービス自体)2トークンを使ってバックエンド B の API を呼ぶ3
POST /oidc/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=batch-service
&client_secret=xxx
&scope=api:internal

Device Authorization

キーボード入力が困難なデバイス向け。

OIDC Providerユーザー(スマホのブラウザで操作)デバイス(テレビ等)OIDC Providerユーザー(スマホのブラウザで操作)デバイス(テレビ等)画面表示「https://auth.example.com/device にアクセスして コード ABCD-1234 を入力してください」承認を記録loop[数秒間隔でポーリング]POST /device/code → ユーザーコード取得1URL にアクセス2コード入力3ログイン → 承認4POST /token { grant_type=device_code, device_code=xxx }5authorization_pending6トークン発行!7

Implicit(非推奨)

OIDC ProviderブラウザOIDC Providerブラウザhttps://app.com/callback認可リクエスト(response_type=token)1トークンが URL フラグメントで直接返る2

Resource Owner Password(非推奨)

OIDC ProviderアプリユーザーOIDC Providerアプリユーザーパスワードを直接入力パスワードを送信 POST /token { grant_type=password, username=..., password=... }

PKCE の仕組み

PKCE(Proof Key for Code Exchange、ピクシーと読む)は、認可コードの横取り攻撃を防ぐ仕組みです。

何を防ぐか

悪意あるアプリOIDC Provider正規アプリ悪意あるアプリOIDC Provider正規アプリ悪意あるアプリが認可コードを横取り認可リクエスト認可コード発行横取りしたコードでトークン交換成功してしまう!

特にモバイルアプリのカスタムスキーム(myapp://callback)は、別アプリが同じスキームを登録して横取りできます。

PKCE がこれを防ぐ

OIDC ProviderクライアントOIDC Providerクライアントランダム値 code_verifier を生成1そのハッシュ code_challenge を計算2認可リクエストに code_challenge を付ける(GET /authorize?...&code_challenge=E9Melh...&code_challenge_method=S256)3code_challenge を保存4トークン交換時に code_verifier(元の値)を送る(POST /token code_verifier=dBjftJeZ4CVP...)5検証 SHA256(code_verifier) == code_challenge → 一致!→ トークン発行6

例の値:

ハッシュの一方向性により:

誰が使うべきか

クライアント種別PKCEclient_secret推奨
SPA必須持てないPKCE のみ
モバイル必須持てないPKCE のみ
CLI必須持てないPKCE のみ
SSR Web アプリ推奨使える両方(ベスト)

OAuth 2.1 では Confidential Client でも PKCE が必須になる予定です。今から両対応にしておくのが無難。

判断フローチャート

No

Yes

No

Yes

Yes

No(SPA / モバイル)

ユーザーはいる?

Client Credentials

画面でログインできる?

Device Authorization

バックエンドはある?

Authorization Code + PKCE(client_secret も使えるなら両方)

Authorization Code + PKCE(必須)

迷ったら Authorization Code + PKCE が正解です。

セキュリティ比較

フロートークン露出リスクclient_secret 要否PKCE推奨度
Authorization Code低(バックチャネル)必須推奨◎
Authorization Code + PKCE低不要必須◎
Client Credentials低(サーバー間)必須不要◎
Device Authorization低任意不要○
Implicit高(URL に露出)不要不要✗
Resource Owner Password高(パスワード露出)任意不要✗

まとめ

← Back to all posts