認可の仕組みとして利用されるOAuth 2.0とは?用語・フローをわかりやすく解説

知識

現代のWebアプリケーションでは、「Googleアカウントでログイン」や「TwitterでログインしてSNS連携」といった機能が当たり前のように使われています。こうした機能の裏側で動いている仕組みが OAuth 2.0 です。

OAuth 2.0は「認可(Authorization)」のフレームワークであり、ユーザーのパスワードを第三者のアプリケーションに渡すことなく、特定のリソースへのアクセス権を安全に委譲する仕組みを提供します。本記事では、OAuth 2.0を理解するうえで欠かせない 4つのロール・主要な用語・代表的なフロー を丁寧に解説します。

この記事は以下の方を対象としています。

  • OAuth 2.0という言葉は知っているが、仕組みをきちんと理解したい方
  • APIを利用するアプリケーション開発でOAuth認証を実装する予定の方
  • 認証と認可の違いを整理したい方


認証と認可の違いを押さえる

OAuth 2.0の話をする前に、「認証(Authentication)」と「認可(Authorization)」の違いを正確に理解しておくことが重要です。この2つは混同されがちですが、まったく異なる概念です。

用語英語意味
認証Authentication「あなたは誰ですか?」を確認することID・パスワードでのログイン、生体認証
認可Authorization「あなたは何ができますか?」を制御することファイルへのアクセス権、APIの操作範囲

OAuth 2.0 はあくまで認可のフレームワークです。「誰であるか」を証明するものではなく、「何にアクセスできるか」という権限の委譲を扱います。ユーザーのアイデンティティ情報を扱いたい場合は、OAuth 2.0 を拡張した OpenID Connect(OIDC) を利用します。

OpenID Connect(OIDC)はOAuth 2.0の上に「認証」層を追加した仕様です。OAuth 2.0がアクセストークンを発行するのに対し、OIDCはIDトークン(JWT形式)を発行してユーザーの本人確認も行います。「Googleアカウントでログイン」機能は多くの場合OIDCを利用しています。


OAuth 2.0 に登場する 4 つのロール

OAuth 2.0に登場する4つのロール(リソースオーナー・クライアント・認可サーバー・リソースサーバー)の関係図

OAuth 2.0では、4つの登場人物(ロール)が明確に定義されています。各ロールの役割を理解することが、フローを正確に把握するための第一歩です。


リソースオーナー(Resource Owner)

リソースオーナーは、保護されたリソース(データ)の所有者です。多くの場合、これはエンドユーザー(人間)を指します。たとえば、Googleカレンダーのデータを所有しているGoogleアカウントのユーザーがリソースオーナーにあたります。

リソースオーナーは、自分のリソースへのアクセスを第三者アプリケーションに許可するかどうかを決定する権限を持っています。


クライアント(Client)

クライアントは、リソースオーナーの代わりにリソースへのアクセスを要求するアプリケーションです。Webアプリケーション、モバイルアプリ、デスクトップアプリ、CLIツールなどさまざまな形態があります。

クライアントはサーバーサイドで動作するかどうかによって、以下の2種類に分類されます。

種類説明
コンフィデンシャルクライアントclient_secret を安全に保管できる環境で動作するサーバーサイドWebアプリ
パブリッククライアントclient_secret を安全に保管できない環境で動作するSPA・モバイルアプリ・デスクトップアプリ


認可サーバー(Authorization Server)

認可サーバーは、リソースオーナーの認証を行い、同意を得たうえでクライアントにアクセストークンを発行するサーバーです。OAuth 2.0の中核となる存在であり、トークンの発行・管理・検証を担当します。

代表的な認可サーバーの実装例としては、Auth0・Keycloak・AWS Cognito・Google Identity Platform などがあります。


リソースサーバー(Resource Server)

リソースサーバーは、保護されたリソース(APIなど)をホストするサーバーです。クライアントからのリクエストを受け取り、アクセストークンを検証したうえで、適切なリソースを返します。

認可サーバーとリソースサーバーは同一のサーバーが担う場合もありますが、大規模なシステムでは分離されることが一般的です。


OAuth 2.0 の主要な用語

OAuth 2.0 のフローを理解するには、いくつかの用語を事前に把握しておく必要があります。以下に主要な用語をまとめます。

アクセストークン(Access Token)

アクセストークンは、クライアントがリソースサーバーのAPIを呼び出すために使用する証明書(クレデンシャル)です。認可サーバーから発行され、HTTPリクエストの Authorization ヘッダーに Bearer トークンとして付与して使用します。

GET /api/calendar/events HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

アクセストークンには有効期限が設けられており、短命(通常1時間程度)なのが特徴です。有効期限が切れると、リフレッシュトークンを使って新しいアクセストークンを取得します。


リフレッシュトークン(Refresh Token)

リフレッシュトークンは、アクセストークンの有効期限が切れたときに新しいアクセストークンを取得するために使われる、長期間有効なトークンです。リフレッシュトークンは認可サーバーにのみ送信され、リソースサーバーには送らないため、漏洩リスクが低く保たれます。

トークン種類有効期限送信先用途
アクセストークン短い(数分〜1時間程度)リソースサーバーAPI呼び出しの認可
リフレッシュトークン長い(数日〜数ヶ月)認可サーバーのみアクセストークンの再取得


スコープ(Scope)

スコープは、クライアントが要求するアクセス権限の範囲を表す文字列です。スコープによって「どのリソースに」「どんな操作が」できるかを制限します。

例として、Google APIのスコープを見てみましょう。

# Googleカレンダーの読み取り権限のみ要求する場合
scope=https://www.googleapis.com/auth/calendar.readonly

# Gmailの送信権限のみ要求する場合
scope=https://www.googleapis.com/auth/gmail.send

# 複数のスコープをスペース区切りで指定する場合
scope=profile email https://www.googleapis.com/auth/calendar.readonly

リソースオーナーはクライアントが要求したスコープを同意画面で確認し、許可するかどうかを選択できます。最小権限の原則に従い、必要最小限のスコープのみ要求することがセキュリティ上のベストプラクティスです。


認可コード(Authorization Code)

認可コードは、認可サーバーがリソースオーナーの同意後にクライアントへ発行する一時的なコードです。クライアントはこの認可コードを使って、認可サーバーにアクセストークンを要求します。

認可コードは非常に短命(通常10分以内)で、1度しか使用できません。仮に傍受されても、それ単体ではアクセストークンを取得できない仕組みになっています(サーバーの client_secret が必要なため)。


グラントタイプ(Grant Type)

グラントタイプは、クライアントがアクセストークンを取得するための方法(フロー)の種類を指します。アプリケーションの種類や用途に応じて適切なグラントタイプを選択します。

認可コードフロー(Authorization Code Flow)

OAuth 2.0 認可コードフロー(Authorization Code Flow)のシーケンス図

認可コードフローは OAuth 2.0 で最も広く使われる、かつ最もセキュアなフローです。サーバーサイドで動作するWebアプリケーションに適しており、アクセストークンがブラウザのURLに露出しないという特徴があります。

上の図のシーケンスを順を追って説明します。

  1. ① サービスへのアクセス要求:ユーザーがクライアント(Webアプリ)上で「Googleでログイン」などのボタンをクリックします。
  2. ② 認可エンドポイントへリダイレクト:クライアントはユーザーのブラウザを認可サーバーの認可エンドポイントへリダイレクトします。このとき、client_idredirect_uriscopestate などのパラメータを付与します。
  3. ③ ログイン画面・同意画面の表示:認可サーバーはユーザーにログイン画面(未認証の場合)と、クライアントが要求するスコープの同意画面を表示します。
  4. ④ ユーザー認証 + アクセス同意:ユーザーが認証情報を入力し、スコープへのアクセスを「許可」します。
  5. ⑤ 認可コードの発行:認可サーバーはリダイレクトURIに認可コードを付与してクライアントへリダイレクトします(URLパラメータ)。
  6. ⑥ 認可コードでトークン要求:クライアントは認可コード・client_idclient_secretredirect_uri を使って、認可サーバーのトークンエンドポイントにアクセストークンを要求します(サーバー間通信)。
  7. ⑦ アクセストークンの発行:認可サーバーが検証を行い、アクセストークン(およびリフレッシュトークン)を返します。
  8. ⑧ トークン付きでAPIリクエスト:クライアントは取得したアクセストークンをAuthorizationヘッダーに付与してリソースサーバーのAPIを呼び出します。
  9. ⑨ 保護されたリソースの返却:リソースサーバーはトークンを検証し、問題がなければリソースを返します。

stateパラメータとCSRF対策:認可リクエスト時に state パラメータとしてランダムな値を付与し、コールバック時に同じ値が返ってきたかを確認します。これにより、CSRF(クロスサイトリクエストフォージェリ)攻撃を防ぐことができます。


PKCE(Proof Key for Code Exchange)とは

PKCE(ピクシー)は、認可コードフローにおける認可コード横取り攻撃を防ぐための拡張仕様です(RFC 7636)。client_secret を安全に保管できないパブリッククライアント(SPA・モバイルアプリ)での利用が特に推奨されており、OAuth 2.1では必須仕様となっています。

PKCEの仕組みは以下のとおりです。

  1. code_verifier の生成:クライアントはランダムな文字列(43〜128文字)を生成します。これを code_verifier と呼びます。
  2. code_challenge の生成:code_verifier をSHA-256でハッシュ化し、Base64URLエンコードした値を code_challenge とします。
  3. 認可リクエストに code_challenge を付与:認可エンドポイントへのリクエスト時に code_challengecode_challenge_method=S256 を送信します。
  4. トークンリクエスト時に code_verifier を送信:認可コードとともに元の code_verifier を送信します。認可サーバーがSHA-256でハッシュ化して code_challenge と一致するか検証します。
// code_verifier の生成(例)
const array = new Uint8Array(32);
crypto.getRandomValues(array);
const codeVerifier = btoa(String.fromCharCode(...array))
  .replace(/+/g, '-')
  .replace(///g, '_')
  .replace(/=/g, '');

// code_challenge の生成(SHA-256 + Base64URL)
async function generateCodeChallenge(verifier) {
  const encoder = new TextEncoder();
  const data = encoder.encode(verifier);
  const digest = await crypto.subtle.digest('SHA-256', data);
  return btoa(String.fromCharCode(...new Uint8Array(digest)))
    .replace(/+/g, '-')
    .replace(///g, '_')
    .replace(/=/g, '');
}


4つのグラントタイプ

OAuth 2.0の4つのグラントタイプ比較表(認可コード・PKCE・クライアントクレデンシャル・インプリシット)

OAuth 2.0 では、利用シーンに応じた複数のグラントタイプが定義されています。それぞれの特徴と推奨度を確認しましょう。


認可コードフロー(Authorization Code Grant)

前述のとおり、最も標準的かつセキュアなフローです。サーバーサイドWebアプリケーションで使用します。client_secret をサーバー側で安全に保管できるコンフィデンシャルクライアントに適しています。


PKCE付き認可コードフロー(Authorization Code with PKCE)

SPA(シングルページアプリケーション)やモバイルアプリなど、client_secret を安全に保管できないパブリッククライアントに適したフローです。PKCEを使ってセキュリティを担保します。現在はSPA・モバイルアプリ向けの事実上の標準となっています。


クライアントクレデンシャルフロー(Client Credentials Grant)

ユーザー(リソースオーナー)が介在しない、サーバー間通信(M2M: Machine to Machine)に適したフローです。クライアントが自分自身の認証情報(client_idclient_secret)を使って直接アクセストークンを取得します。

# クライアントクレデンシャルフローでのトークン取得例
curl -X POST https://auth.example.com/oauth/token 
  -H "Content-Type: application/x-www-form-urlencoded" 
  -d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=read:data"


インプリシットフロー(Implicit Grant)- 非推奨

かつてSPAで広く使われていたフローですが、現在は非推奨となっています。アクセストークンがURLフラグメントに直接含まれるため、ブラウザの履歴やRefererヘッダーを通じてトークンが漏洩するリスクがあります。SPAでは代わりにPKCE付き認可コードフローを使用してください。

リソースオーナーパスワードクレデンシャルフロー(ROPC)について:ユーザーのIDとパスワードをクライアントが直接受け取るフローです。第三者機関への認証委譲というOAuthの本来の目的に反するため、非推奨となっています。どうしても使用する場合はクライアントがサービスの公式アプリである場合のみに限定してください。


エンドポイントの種類

OAuth 2.0 では、認可サーバーが提供するいくつかのエンドポイント(URLパス)を通じてやり取りが行われます。

エンドポイント役割使用フロー
認可エンドポイント(/authorize)ユーザーの認証・同意画面を提供し、認可コードを発行する認可コードフロー
トークンエンドポイント(/token)認可コードやクレデンシャルを受け取り、アクセストークンを発行する全グラントタイプ
リフレッシュエンドポイント(/token)リフレッシュトークンを使って新しいアクセストークンを発行するリフレッシュトークンフロー
イントロスペクションエンドポイント(/introspect)アクセストークンの有効性・メタデータを確認するトークン検証
失効エンドポイント(/revoke)アクセストークンまたはリフレッシュトークンを失効させるログアウト処理


OAuth 2.0 のセキュリティ上の注意点

OAuth 2.0 を正しく実装するためには、セキュリティに関する注意点を把握しておく必要があります。

  • redirect_uri の厳密な検証:認可サーバーは事前に登録されたリダイレクトURIのみ許可します。ワイルドカードによる登録は避け、完全一致での検証を行いましょう。
  • state パラメータの使用:CSRF攻撃を防ぐために、認可リクエストごとにランダムな state 値を生成し、コールバック時に検証します。
  • アクセストークンの安全な保管:ブラウザのローカルストレージへのトークン保存はXSS攻撃のリスクがあります。SPAではHttpOnly Cookieやメモリ内での保管を検討してください。
  • HTTPS の使用:認可エンドポイント・トークンエンドポイントはすべてHTTPS(TLS)を使用する必要があります。
  • 最小限のスコープ:必要最小限のスコープのみ要求し、不必要な権限を持つトークンを発行しないようにします。
  • アクセストークンの有効期限を短く:有効期限を短く設定することで、トークンが漏洩した場合の被害を最小化できます。


OAuth 2.1 での変更点

OAuth 2.1 は、OAuth 2.0 のベストプラクティスを統合して整理した新しいドラフト仕様です(執筆時点ではまだドラフト段階)。主な変更点は以下のとおりです。

  • PKCE が必須:認可コードフローでのPKCEの使用が必須となります。
  • インプリシットフローの廃止:インプリシットグラントが仕様から削除されます。
  • ROPCフローの廃止:リソースオーナーパスワードクレデンシャルフローが削除されます。
  • redirect_uri の完全一致:リダイレクトURIは完全一致での検証が必須となります。

今から新規に実装する場合は、OAuth 2.1 のベストプラクティスに沿って設計することを推奨します。


まとめ

本記事では、OAuth 2.0 の基本概念を以下の観点から解説しました。

  • 認証と認可の違い:OAuth 2.0 はあくまで認可のフレームワーク(認証にはOpenID Connectを使用)
  • 4つのロール:リソースオーナー・クライアント・認可サーバー・リソースサーバー
  • 主要な用語:アクセストークン・リフレッシュトークン・スコープ・認可コード・グラントタイプ
  • 代表的なフロー:認可コードフロー(サーバーサイド向け)・PKCE付き認可コードフロー(SPA・モバイル向け)・クライアントクレデンシャルフロー(M2M向け)
  • セキュリティ:HTTPS必須・redirect_uri検証・state パラメータ・トークンの安全な保管

OAuth 2.0 を正しく理解することで、安全なAPI連携やSSO(シングルサインオン)の実装が可能になります。実装時には公式のRFC仕様書(RFC 6749、RFC 7636)や利用する認可サーバーの公式ドキュメントを必ず参照するようにしましょう。


参考リソース

コメント

タイトルとURLをコピーしました