RFC 6749: OAuth 2.0
パスワードを渡さずに「この範囲だけ許可する」を実現するOAuth 2.0の原典RFC 6749を精読し、4つのロールと認可コードフロー、PKCE時代の正しいグラント選択までを体系的に理解できる。
- RFC 6749(2012年)は署名が複雑なOAuth 1.0(RFC 5849)を置換した認可枠組み。所有者・クライアント・認可サーバー・リソースサーバーの4役と、トークンによる権限委譲を定義する。
- 中核の認可コードグラントは、ブラウザ経由のリダイレクトで短命の認可コードを受け取り、クライアントが裏の経路で直接トークンと交換する二段構えのフローだ。取得したトークンをAPIへ運ぶBearer方式は、同時発行のRFC 6750が定める。
- implicitとパスワードグラントは非推奨となり、公開クライアントはPKCE(RFC 7636、2015年)付き認可コードが標準になった。OAuth 2.1はこの安全な構成へ整理する。
このRFCが決めたこと
横にスクロール
RFC 6749(2012年10月)は、OAuth 2.0認可フレームワークを定義した文書だ。解決したかった課題は「パスワードの又貸し」である。あるアプリに自分のデータへのアクセスを許したいとき、かつてはそのアプリへユーザー名とパスワードそのものを預けるしかなかった。これでは全権限を無期限に渡すことになり、取り消す手段は実質パスワード変更しかない。OAuthはパスワードの代わりに、範囲(scope)と期限を限定したアクセストークンを発行する枠組みを標準化し、「このアプリに、この範囲だけ、この期間だけ」という委譲を可能にした。
前身のOAuth 1.0(RFC 5849、2010年)はリクエストごとの署名計算が複雑で、実装の敷居が高かった。6749はこれを置き換え、署名の代わりにTLSを前提とした平易な設計へ改めた。ただし6749が定めるのはトークンを取得するまでの手順であり、取得したトークンをAuthorizationヘッダに載せてAPIへ運ぶ方法は、同時発行のRFC 6750(Bearerトークン)が受け持つ。
6749のタイトルは「認可フレームワーク」であって、単一のプロトコルではない。トークンの形式もscope文字列の意味も定めず、多くを拡張点として残した。この柔軟さが幅広い普及を生んだ一方、安全な組み合わせを選ぶ責任は実装者に残った。後のセキュリティBCPやOAuth 2.1は、その「選び方」を絞り込む作業だと言える。
要点の精読
4つのロール
6749は登場人物を4つのロールへ分離した。この整理が仕様全体の土台になる。
| ロール | 役割 | 例 |
|---|---|---|
| リソースオーナー | 保護されたリソースの持ち主として許可を与える | エンドユーザー |
| クライアント | 許可を得てリソースへアクセスするアプリ | Webアプリ・モバイルアプリ |
| 認可サーバー | 同意を確認しアクセストークンを発行する | 各サービスのID基盤 |
| リソースサーバー | トークンを検証してリソースを返す | 写真や連絡先のAPI |
要点は、許可を与える者・発行する者・検証する者が別のロールとして定義されていることだ。この分離があるからこそ、APIを提供するリソースサーバーはユーザーのパスワードに一切触れずに済む。
認可コードグラントのフロー
中核が認可コードグラント(authorization code grant)だ。ユーザーのブラウザを経由する「表の経路」と、クライアントと認可サーバーが直接通信する「裏の経路」を使い分ける二段構えになっている。
1. クライアントがユーザーのブラウザを認可サーバーへ誘導
GET /authorize?response_type=code&client_id=s6BhdRkqt3
&redirect_uri=https://client.example/cb&state=xyz
2. ユーザーが同意すると、認可コード付きでクライアントへ戻る
HTTP/1.1 302 Found
Location: https://client.example/cb?code=SplxlOBeZQ...&state=xyz
3. クライアントが裏の経路でコードをトークンと交換
POST /token
grant_type=authorization_code&code=SplxlOBeZQ...
&redirect_uri=https://client.example/cb
ブラウザ上を流れるのは短命の引換券である認可コードだけで、アクセストークン本体は裏の経路でしか渡されない。コードの有効期間は短く(仕様は最大10分を推奨)、再利用は禁止されている。トークンという本丸をブラウザ履歴やURLにさらさないことが、この設計の核心だ。なお、ここで登場するリダイレクトや401応答の意味論は、RFC 9110が定めるHTTPの土台の上に成り立っている。
4つのグラントタイプと現在の扱い
6749は認可コードのほかに3つのグラントタイプを定義したが、発行後10年余りで評価は大きく塗り替えられた。
| グラントタイプ | 想定用途 | 現在の扱い |
|---|---|---|
| 認可コード | ユーザーが関与する認可全般 | PKCE併用で標準 |
| implicit | ブラウザ内アプリ向けの簡略フロー | 非推奨 |
| リソースオーナーパスワードクレデンシャル | パスワードを直接預かる移行用 | 非推奨 |
| クライアントクレデンシャル | ユーザー不在のサーバー間通信 | 現役 |
implicitはトークン交換の手順を省き、アクセストークンをURLフラグメントで直接返す簡略版だった。しかしトークンがブラウザ履歴や中間のログへ残りやすく、受け取ったトークンが本当に自分宛てかを確かめる手段も乏しい。リソースオーナーパスワードクレデンシャルに至っては、クライアントがパスワードを直接預かる構造であり、OAuthが排除したかった「又貸し」の再来だった。両者はOAuth 2.0セキュリティBCP(RFC 9700、2025年1月)で正式に非推奨とされ、統合改訂版であるOAuth 2.1ドラフトでは仕様から削除される方向にある。
代わって公開クライアントの標準となったのがPKCE(RFC 7636、2015年9月)だ。クライアントシークレットを安全に保持できないモバイルアプリやSPAでも、リクエストごとに生成する検証値の照合によって、認可コードを受け取った者とトークンへ交換する者の同一性を証明できる。OAuth 2.1ドラフトでは、公開クライアントに限らず認可コードグラント全般でPKCEを必須とする方向で整理が進んでいる。
アクセストークンとリフレッシュトークンの分担
トークンは2種類で役割を分担する。アクセストークンはリソースサーバーへ提示する短命の鍵で、漏えいしても期限切れで被害が止まるよう寿命を絞る。リフレッシュトークンは認可サーバーだけに提示する長命の鍵で、ユーザーを再度煩わせずにアクセストークンを再発行するために使う。提示先が異なる点が肝心で、リフレッシュトークンがリソースサーバーへ流れることはない。
また6749はトークンの形式を規定していない。ランダムな参照文字列でも、中身に情報を自己記述するJWTでもよい。JWT形式ならJWTデコーダで構造を確認できるが、それは発行側の実装選択であって、クライアントはトークンを不透明な文字列として扱うのが原則だ。
redirect_uriの厳密一致とstate
認可コードはredirect_uriで指定されたURLへ届く。この宛先の検証が甘いと、コードが攻撃者の用意した先へ届きかねない。仕様は、完全なredirect_uriが登録されている場合に単純文字列比較での照合を求め、後続のセキュリティBCPは常に厳密一致で検証するよう強化した。ワイルドカードや前方一致での照合は避けるべきだ。
stateパラメータは、クライアントが認可リクエスト時に発行し、リダイレクトで戻ってきた値と突き合わせる推測困難な値だ。これで「いま届いた応答は自分が開始したフローの続きか」を確認でき、偽の応答を注入して他人のアカウントを紐付けさせるようなCSRFを防げる。6749では推奨扱いだが実装では必須と考えるべきで、OAuth 2.1ドラフトではPKCEがこの防御の多くを兼ねる形へ整理されている。
つまずきやすい点
最大の誤解は、OAuthを認証プロトコルとして使ってしまうことだ。6749が定めるのはリソースへのアクセスを許可する枠組みであり、目の前のユーザーが誰かを保証する仕組みではない。アクセストークンを持っていることは本人であることの証明にならない。ログイン機能が必要なら、OAuth 2.0の上に本人確認のレイヤーを載せたOpenID Connect(2014年)を使うのが正解だ。
次に、古い解説を参考にimplicitフローを新規採用してしまう例がいまだに絶えない。SPAだからimplicitという時代は終わっており、現在はSPAもモバイルもPKCE付き認可コードグラントの一択だ。stateの省略や緩いredirect_uri照合も、ライブラリ任せの実装では見落としやすい。省略可能に見える防御こそ明示的に有効化しておく姿勢は、セキュリティ全般に通じる基本だ。
OAuthのフローは、stateやPKCEを省いても一応は動いてしまう。防御の欠落は正常系の動作確認では見つからない。仕様とBCPが求める防御は、最初からすべて有効にして実装するのが正しい。
まとめ
RFC 6749は、パスワードを渡さない委譲アクセスという発想をWeb標準に押し上げた。ただし原文の4グラントをそのまま使う時代は終わり、現在の実践は「認可コードとPKCEを使い、implicitとパスワードグラントは使わない」に収束している。RFC 9700とOAuth 2.1ドラフトまで併読すれば、フレームワークの自由度を安全側へ倒す道筋が見える。他のRFC解説はRFC精読から辿れる。
RFC精読の記事ガイド
RFC 6749: OAuth 2.0を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
RFC
比較で見る軸
難易度: advanced / カテゴリ: RFC精読 / タグ数: 5
導入後に効く点
中核の認可コードグラントは、ブラウザ経由のリダイレクトで短命の認可コードを受け取り、クライアントが裏の経路で直接トークンと交換する二段構えのフローだ。取得したトークンをAPIへ運ぶBearer方式は、同時発行のRFC 6750が定める。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- RFC精読
- タグ数
- 5
判断チェックリスト
- 自社の用途が「RFC / OAuth」に近いか確認する。
- 強みである「RFC 6749(2012年)は署名が複雑なOAuth 1.0(RFC 5849)を置換した認可枠組み。所有者・クライアント・認可サーバー・リソースサーバーの4役と、トークンによる権限委譲を定義する。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。