OAuth 2.0 完全ガイド:認可コードフローとPKCE、トークン管理・実装上のセキュリティ対策

OAuthとは — 概要と目的

OAuth(オーオース、正式には OAuth 2.0 が広く使われます)は、ユーザー(Resource Owner)が自身の資格情報(ユーザー名/パスワード)を第三者アプリ(Client)に渡さずに、別のサービス(Resource Server)上の保護されたリソースへのアクセス権を委譲(デリゲーション)するためのプロトコルです。つまり「認証(Authentication)」ではなく「認可(Authorization)」を扱う仕組みであり、認証が必要な場合は OpenID Connect(OIDC)などの上位仕様を用います。

主要な登場人物(ロール)

  • Resource Owner:リソースの所有者(通常はエンドユーザー)
  • Client:リソースにアクセスを求めるアプリケーション(ウェブアプリ、モバイルアプリ、API クライアントなど)
  • Authorization Server:認可を行うサーバ(ユーザー認証、同意処理、トークン発行等を行う)
  • Resource Server:保護されたリソースを提供するサーバ(アクセストークンを検証してリソースへのアクセスを許可する)

主要コンポーネント(トークンとスコープ)

OAuthで重要なのは「トークン」。代表的なものは以下です。

  • アクセストークン(Access Token):リソースサーバに提示して API 等へアクセスするためのトークン。Bearer トークンとして送られるのが一般的。内部形式は JWT(JSON Web Token)や不透明な文字列(opaque)などさまざま。
  • リフレッシュトークン(Refresh Token):アクセストークンの有効期限が切れた際に新しいアクセストークンを取得するためのトークン。長期間有効にされることが多いが、扱いは慎重にする必要がある(特に公開クライアントでは危険)
  • IDトークン(ID Token):OpenID Connect においてユーザーの認証情報を含む JWT。認可ではなく認証に使う。
  • スコープ(scope):トークンに付与される権限の範囲を表す文字列。最小権限の原則に基づいた設計が推奨される。

主要な認可フロー(Grant Types)

代表的なフローとその用途:

  • Authorization Code Grant(認可コードフロー):サーバーサイドアプリや SPA(PKCE併用)で推奨される。ユーザーが認可サーバでログイン・同意し、認可コードを受け取り、それを用いて認可サーバへトークン交換を行う。コード横取り攻撃対策として PKCE(Proof Key for Code Exchange、RFC 7636)を使う。
  • Implicit Flow(インプリシット):かつて SPA 向けに使われたが、セキュリティ欠点のため現代では非推奨(OAuth 2.1 で削除予定)。アクセストークンをフロントチャネルで直接受け取り、トークン漏洩のリスクが高い。
  • Client Credentials Grant(クライアント認証):マシン間通信(バックエンド間)で使われる。ユーザーを介さず、クライアントが直接アクセストークンを取得する。
  • Resource Owner Password Credentials(パスワード):ユーザーが直接クライアントに認証情報を渡すタイプ。原則非推奨で、信頼されたクライアント以外では使用すべきでない。
  • Device Authorization Grant(デバイスコード):入力手段が限られたデバイス(スマートTV等)で使うフロー(RFC 8628)。ユーザーが別デバイスで承認を行う。

実装上のプロセス(認可コードフローの典型例)

典型的な認可コードフローの手順(PKCEを含む):

  • ① クライアントがブラウザを通じて Authorization Endpoint (/authorize) へリクエスト。クライアントID、リダイレクトURI、scope、state、code_challenge(PKCE)などを送る。
  • ② ユーザーが認可サーバでログイン・同意(ユーザーエージェントで)。
  • ③ 認可サーバは認可コードをリダイレクトURIに返す(stateで CSRF 防止)。
  • ④ クライアントはその認可コードと code_verifier を /token エンドポイントに送ってアクセストークン(とオプションでリフレッシュトークン)を取得する。
  • ⑤ クライアントはアクセストークンを用いて Resource Server の API へアクセスする(Authorization: Bearer トークンヘッダ)。

セキュリティ上のポイントと攻撃対策

OAuth を安全に運用するための主要な注意点:

  • TLS(HTTPS)の必須化:全てのエンドポイントで TLS を必須にする(トークン漏洩対策)。
  • PKCE の利用:認可コードフローでは必ず PKCE を使う。公開クライアント(ブラウザやネイティブ)では必須。
  • state パラメータで CSRF を防止:認可応答の整合性を確認する。
  • アクセストークンの短い有効期間とリフレッシュトークン管理:有効期間を短くして万一の漏洩リスクを下げる。リフレッシュトークンのローテーションや取り消しを検討する(RFC 7009など)。
  • スコープ設計:過剰な権限を与えない。最小権限。
  • トークン形式の選択:JWT(自己完結)を使う場合は署名と検証の管理(公開鍵ローテーションや期限管理)を厳格に。opaque トークンなら introspection(RFC 7662)で検証する。
  • Implicit Flow の回避:フロントチャネルでアクセストークンを受け取るフローは避け、PKCE + Authorization Code を用いる。

OAuth 1.0a と OAuth 2.0 の違い、OIDC の位置づけ

OAuth 1.0a(古い仕様)は署名ベースで通信の完全性を保証していました。OAuth 2.0 は設計を簡素化し、トークンベース(Bearer)で運用しますが、その分運用上のセキュリティ対策が重要です。認証を目的とする場合は OAuth 2.0 の上に OpenID Connect(OIDC)を重ね、ID Token や UserInfo エンドポイントを利用します。OIDC は OAuth を認証にも安全に使うための拡張仕様です。

実運用でのベストプラクティス

  • Authorization Server と Resource Server を明確に分離し、トークン検証の責務を整理する。
  • OAuth 2.1(草案)や最新の IETF RFC、OWASP のガイドラインに従う。OAuth 2.1 は既存のベストプラクティスを統合し、Implicit フローを廃止するなどの勧告を提示している。
  • ライブラリやフレームワークは信頼された実装を利用し、自前実装は避ける(脆弱性を招きやすい)。
  • ログと監査を充実させ、異常なトークン利用を検知する。

よくある導入ケースと注意点

  • Web アプリ(サーバーサイド):認可コードフロー + サーバ間でのトークン保管が一般的。クライアントシークレットを安全に保管できる。
  • SPA(シングルページアプリ):過去はインプリシットが用いられたが、現在は認可コード + PKCE が推奨。アクセストークンは可能であれば短命にし、セキュアなストレージを使う。
  • モバイル・ネイティブアプリ:認可コード + PKCE を採用。ネイティブ向けリダイレクト(カスタムURIスキームや証明書ピンニング等)に注意。
  • サーバ間連携:クライアント認証(Client Credentials Grant)で十分だが、スコープ分離やクライアント証明書の利用を検討。

用語・プロトコル参照(主な RFC と仕様)

実装や詳細確認のために参照すべき主要文書:

  • OAuth 2.0 Core: RFC 6749
  • OAuth 2.0 Bearer Token Usage: RFC 6750
  • PKCE: RFC 7636
  • Token Revocation: RFC 7009
  • Token Introspection: RFC 7662
  • Device Authorization Grant: RFC 8628
  • Authorization Server Metadata: RFC 8414
  • OAuth 2.1(草案): 最新のベストプラクティス集約(ワーキングドラフト)
  • OpenID Connect Core 1.0(OIDC): 認証の拡張仕様

まとめ

OAuth は「ユーザーのパスワードを第三者に渡さずにリソースへのアクセスを委譲する」ための強力な仕組みです。ただし設計・実装を誤るとトークン漏洩や不正アクセスのリスクが高まるため、PKCE・HTTPS・短命なアクセストークン・最小権限スコープ・適切なトークン管理(リフレッシュトークンのローテーションや取り消し)などのベストプラクティスに従って実装することが重要です。認証が必要な場合は OIDC を併用してください。

参考文献