
OAuth 2.0 / OpenID Connect 入門 - 認可と認証の違い、Authorization Code Flow + PKCE まで
「Google でログイン」や外部 API 連携で必ず出てくる OAuth 2.0 と OpenID Connect(OIDC)。なんとなく使ってはいても、「OAuth は認証じゃないの?」「access token と ID token は何が違う?」「Implicit Flow はもう使っちゃダメ?」あたりは曖昧になりがちです。
この記事では、Web アプリ開発者向けに、OAuth と OIDC の違い・登場人物・トークンの役割・推奨フローを、RFC 6749 / 7636 / 6750 / 9700 と OpenID Connect Core 1.0、そして OAuth 2.1 ドラフトを一次ソースに整理します。
OAuth(認可)と OIDC(認証)は何が違うか
まず最重要の区別です。
- OAuth 2.0 は「認可(authorization)」の仕組みです。「このアプリにあなたのカレンダーを読む権限を与えてよいか」を扱います。RFC 6749 の冒頭でも、third-party application に対して HTTP サービスへの限定的なアクセス権を与える枠組みだと定義されています。
- OpenID Connect は「認証(authentication)」の仕組みです。「ログインしているのは誰か」を扱います。OIDC Core 1.0 はこれを「OAuth 2.0 プロトコルの上に乗る、シンプルな identity layer」と定義しています。
つまり OAuth 単体は「誰がログインしているか」を保証する規格ではありません。ユーザー認証(サインイン)をやりたいなら、OAuth の上に OIDC を重ねるのが正しい設計です。「OAuth でログイン」と言われるものの多くは、実態としては OIDC を使っています。
NOTE
「OAuth = ログイン」という説明は不正確です。OAuth はアクセス権の委譲(認可)であって、本人確認(認証)はそのままでは扱いません。認証を標準的にやるための層が OIDC です。
登場人物(役割)
OAuth のフローは、次の役割の登場人物のやり取りとして理解すると整理しやすいです(RFC 6749 の用語)。
| 役割 | 英語 | 説明 |
|---|---|---|
| リソースオーナー | Resource Owner | 保護されたリソースの持ち主。多くの場合エンドユーザー本人 |
| クライアント | Client | リソースにアクセスしたいアプリ(あなたが作る Web/モバイルアプリ) |
| 認可サーバー | Authorization Server | ユーザーを認証し、同意を得てトークンを発行するサーバー |
| リソースサーバー | Resource Server | アクセストークンを受け取り、保護されたリソース(API)を提供するサーバー |
クライアントには2種類あります。RFC 6749 はこれを機密クライアント(confidential client)と公開クライアント(public client)に分類します。
- 機密クライアント: クライアントシークレットを安全に保持できる。サーバーサイドの Web アプリなど。
- 公開クライアント: シークレットを秘密にできない。SPA(ブラウザ内 JS)やネイティブアプリなど。
この区別が、後述する PKCE がなぜ重要かに直結します。
Authorization Code Flow + PKCE の流れ
現在もっとも推奨される基本フローが Authorization Code Flow(認可コードフロー)に PKCE を組み合わせたものです。PKCE(Proof Key for Code Exchange、「ピクシー」と読む)は RFC 7636 で定義されています。
考え方はこうです。
- クライアントは毎回ランダムな code_verifier を生成し、そのハッシュ(code_challenge)を認可リクエストに付ける。
- 後でトークンと引き換える際に、元の code_verifier を提示する。
- 認可サーバーはハッシュが一致するか検証する。
これにより、たとえ認可コードが途中で盗まれても、code_verifier を知らない攻撃者はトークンを取得できません。
認可リクエストの URL はおおよそ次のようになります。ブラウザでこの URL へリダイレクトします。
GET /authorize?response_type=code
&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&scope=openid%20profile%20email
&state=af0ifjsldkj
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256 HTTP/1.1
Host: auth.example.comユーザーがログイン・同意すると、認可サーバーは redirect_uri に認可コードを付けて返します。クライアントはそのコードをトークンエンドポイントに POST して、トークンと交換します。
curl -X POST https://auth.example.com/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d code=SplxlOBeZQQYbYS6WxSbIA \
-d redirect_uri=https://app.example.com/callback \
-d client_id=s6BhdRkqt3 \
-d code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXkポイントは、access token がブラウザのアドレスバー(URL)に乗らないことです。コードだけがリダイレクトで返り、トークンはサーバー間(または XHR)の安全な経路で受け取れます。これが後述の Implicit Flow との決定的な違いです。
各種トークンの役割
OAuth/OIDC で出てくるトークンは役割が違います。混同しないことが大事です。
| トークン | 規格 | 役割 | 形式 | 渡す相手 |
|---|---|---|---|---|
| access token | OAuth 2.0 | API へのアクセス権を表す。「何ができるか」 | 不透明文字列 or JWT | リソースサーバー(API) |
| refresh token | OAuth 2.0 | access token を再発行するための長命トークン | 不透明文字列 | 認可サーバーのみ |
| ID token | OpenID Connect | 認証結果。「誰がいつログインしたか」 | JWT | クライアント自身 |
重要な注意点をいくつか。
- access token はクライアントが中身を解釈してはいけません。クライアントにとっては「リソースサーバーへ渡すための不透明な文字列」です。形式が JWT でも、それはリソースサーバー側の都合です。
- アクセストークンの使い方は RFC 6750(Bearer Token)が定めており、
Authorization: Bearer <token>ヘッダで送るのが基本です。 - ID token は逆にクライアントが検証して読むためのものです。OIDC Core 1.0 が「ID Token は JWT として表現される」と定義しており、
sub(ユーザー識別子)やiss/aud/exp、認証時刻auth_timeなどのクレームを含みます。 - ユーザーのプロフィール詳細が欲しいときは、ID token に頼りきらず UserInfo エンドポイントに access token を提示して取得します。
JWT の構造や検証の詳細は JWT(JSON Web Token)の仕組みと正しい使い方 を参照してください。ID token はまさに JWT なので、iss/aud/exp の検証や alg 許可リストの話がそのまま当てはまります。
他のフローと使い分け(と非推奨フロー)
OAuth にはいくつかのフロー(grant type)があります。用途で使い分けますが、歴史的に使われていたが今は非推奨のものもあります。
| フロー | 用途 | 現在の扱い |
|---|---|---|
| Authorization Code + PKCE | Web/SPA/モバイルでのユーザー認可 | 推奨(既定) |
| Client Credentials | ユーザー不在のサーバー間連携(マシン間) | 適切な用途では推奨 |
| Device Authorization(Device Code) | 入力が貧弱な端末(TV など) | 該当用途で利用可 |
| Implicit Flow | かつての SPA 向け | 非推奨 |
| Resource Owner Password Credentials(ROPC) | アプリにパスワードを直接渡す | 非推奨/廃止方向 |
なぜ Implicit Flow は非推奨になったのか
Implicit Flow は、トークンエンドポイントを介さずaccess token を直接リダイレクト(URL フラグメント)で返すフローでした。SPA がまだ CORS で安全にトークン交換しづらかった時代の妥協策です。
これが危険なのは、access token がブラウザの履歴・Referer・ログなどに残りやすく、漏洩しやすいからです。OAuth のセキュリティベストプラクティスである RFC 9700(Best Current Practice for OAuth 2.0 Security、BCP 240、2025年公開)は、Implicit のようなaccess token をリダイレクトで返す方式を使うべきでないとしています。今の SPA は Authorization Code + PKCE を使うべきです。
なぜ ROPC は非推奨なのか
ROPC は、ユーザーが自分の ID とパスワードをクライアントアプリに直接入力し、アプリがそれを認可サーバーに送ってトークンをもらう方式です。これは OAuth が本来避けたかった「アプリにパスワードを預ける」状態そのもので、フィッシングや MFA との相性の悪さもあり、推奨されません。
WARNING
Implicit Flow と ROPC は、OAuth 2.1 ドラフト(後述)では明確に除外(omit)される方向で記述されています。新規実装では使わず、Authorization Code + PKCE か、用途に応じて Client Credentials / Device Code を選んでください。
OAuth 2.1 のステータス(ドラフトであることに注意)
「これからは OAuth 2.1」という話をよく聞きますが、正確に押さえておきたい点があります。
OAuth 2.1 は2026年6月時点で正式な RFC ではなく、IETF のドラフト(Internet-Draft)です。具体的には draft-ietf-oauth-v2-1(執筆時点で -15、2026年3月公開、Standards Track を意図、期限切れは2026年9月予定)という状態です。正式仕様として確定しているわけではないので、「OAuth 2.1 では〜と決まっている」とは断言できません。
ただし方向性は明確で、OAuth 2.1 ドラフトは RFC 6749 と RFC 6750 を統合・整理し、過去10年のベストプラクティスを取り込むものです。具体的には次を標準化しようとしています。
- PKCE を必須化(公開クライアントだけでなく、認可コードフロー全般で)
- redirect_uri の完全一致(exact matching)を必須化
- Implicit Grant と ROPC を除外(廃止方向)
つまり、「OAuth 2.1 ドラフトと RFC 9700 が示す現在のベストプラクティス」を実務の指針にするのが妥当です。PKCE はもはや公開クライアント限定の追加策ではなく、機密クライアントを含めて推奨される、という点は覚えておいてください。
実装時の注意
最後に、実装でつまずきやすい・事故りやすいポイントです。
state で CSRF を防ぐ
認可リクエストに推測不能な state パラメータを付け、コールバックで一致を検証します。これを省くと、攻撃者の認可コードを被害者のセッションに紐付ける CSRF が成立し得ます。CSRF 全般の考え方は Cookie / セッション / SameSite ガイド も参考になります。
PKCE は常に使う
公開クライアントでは必須、機密クライアントでも推奨です。code_challenge_method は S256(SHA-256)を使い、plain は避けます。
redirect_uri は完全一致で検証する
認可サーバー側で、登録済みの redirect_uri と完全一致(前方一致やワイルドカードではなく)で照合します。緩い検証はオープンリダイレクトやコード横取りの入口になります。
トークンの保管場所に注意する
access token / refresh token をどこに置くかは難所です。localStorage は XSS で盗まれます。httpOnly Cookie は XSS に強い一方で CSRF 対策(SameSite など)が要ります。万能解はないので、XSS を塞ぐ前提で用途に応じて選びます。ここは JWT の保管と同じ論点なので JWT の記事 の保存場所の節も合わせて読んでください。
スコープは最小限に
scope で要求する権限は、本当に必要なものだけに絞ります。過剰なスコープ要求は、漏洩時の被害も同意のハードルも上げます。
NOTE
認証方式そのものをより安全にしたいなら、パスワードに依存しない パスキー / WebAuthn との組み合わせも検討の価値があります。OIDC の認可サーバー側でパスキーを使う、といった構成が現実的です。
まとめ
- OAuth 2.0 は認可(アクセス権の委譲)、OIDC は認証(誰がログインしたか)。OIDC は OAuth の上に乗る identity layer
- 登場人物はリソースオーナー / クライアント / 認可サーバー / リソースサーバー。クライアントは機密と公開に分かれる
- 推奨は Authorization Code Flow + PKCE。access token を URL に乗せず、コードを安全にトークンと交換する
- トークンは役割が別。access token は API 用(クライアントは中身を見ない)、refresh token は再発行用、ID token は認証結果の JWT
- Implicit Flow と ROPC は非推奨。RFC 9700(BCP 240、2025年)と OAuth 2.1 ドラフトがその方針を示す
- OAuth 2.1 は2026年6月時点でまだ IETF ドラフト(正式 RFC ではない)。ただし PKCE 必須・redirect_uri 完全一致・Implicit/ROPC 除外という方向は明確
- 実装では state / PKCE(S256) / redirect_uri 完全一致 / トークン保管 / 最小スコープを押さえる
OAuth と OIDC は登場人物とトークンの役割を一度整理すれば、見通しがぐっと良くなります。新規実装は迷わず Authorization Code Flow + PKCE から始めてください。
参考リンク
- RFC 6749: The OAuth 2.0 Authorization Framework
- RFC 7636: Proof Key for Code Exchange (PKCE)
- RFC 6750: OAuth 2.0 Bearer Token Usage
- RFC 9700: Best Current Practice for OAuth 2.0 Security
- draft-ietf-oauth-v2-1: The OAuth 2.1 Authorization Framework(IETF ドラフト)
- OpenID Connect Core 1.0
- JWT(JSON Web Token)の仕組みと正しい使い方(当ブログ)
- Cookie / セッション / SameSite ガイド(当ブログ)
- パスキー / WebAuthn 入門(当ブログ)


