Overview
OAuth 2.0(Open Authorization 2.0)とは、ユーザーがパスワードを第三者に渡すことなく、Webサービスやアプリケーションに対して自分のリソースへの限定的なアクセス権を安全に委譲するための認可フレームワークです。RFC 6749で標準化されています。
たとえば、写真編集アプリがGoogleフォトの写真にアクセスする場合、ユーザーはGoogleのログイン画面でアクセスを許可するだけで、パスワードを写真編集アプリに教える必要はありません。OAuth 2.0はこのような委任認可(Delegated Authorization)のための業界標準プロトコルです。
重要な点として、OAuth 2.0は「認可(Authorization)」のフレームワークであり、「認証(Authentication)」のプロトコルではありません。ユーザーの本人確認(認証)を行う場合は、OAuth 2.0の上に構築されたOpenID Connect(OIDC)を使用します。
Details
OAuth 2.0の主要な登場人物
- リソースオーナー(Resource Owner):保護されたリソースの所有者。通常はエンドユーザー
- クライアント(Client):リソースオーナーに代わってリソースにアクセスするアプリケーション
- 認可サーバー(Authorization Server):リソースオーナーの認証を行い、アクセストークンを発行するサーバー
- リソースサーバー(Resource Server):保護されたリソースをホストし、アクセストークンを検証するサーバー
グラントタイプ(認可フロー)
- 認可コードフロー(Authorization Code Grant):最も安全で推奨されるフロー。サーバーサイドアプリケーション向け。認可コードを経由してアクセストークンを取得し、トークンがブラウザに露出しない
- 認可コード + PKCE(Proof Key for Code Exchange):モバイルアプリやSPA(シングルページアプリケーション)向けの拡張。認可コードの横取り攻撃を防ぐために、コードチャレンジとコードベリファイアを使用。現在はすべてのクライアントでPKCEの使用が推奨
- クライアントクレデンシャルフロー(Client Credentials Grant):マシン間通信(M2M)向け。ユーザーの介在なしにクライアント自身の認証情報でトークンを取得
- デバイスコードフロー(Device Code Grant):スマートTV、IoTデバイスなどブラウザを持たない制限されたデバイス向け。別のデバイス(スマートフォン等)で認可を行う
なお、インプリシットフロー(Implicit Grant)はセキュリティ上の問題から現在は非推奨となっており、代わりにPKCE付き認可コードフローの使用が求められています。
トークンの種類と管理
- アクセストークン(Access Token):リソースサーバーへのAPIリクエストに付与する短命のトークン。通常15分〜1時間の有効期限を設定。JWT(JSON Web Token)形式で発行されることが多い
- リフレッシュトークン(Refresh Token):アクセストークンの有効期限が切れた際に、ユーザーの再認証なしに新しいアクセストークンを取得するための長命トークン。サーバーサイドで安全に保管する必要がある
スコープによるアクセス制御
スコープ(Scope)は、クライアントがアクセスできるリソースの範囲を限定する仕組みです。たとえば、Google APIでは「read:email」でメールの読み取りのみ、「write:calendar」でカレンダーの書き込みのみといった細かい権限制御が可能です。最小権限の原則に基づき、アプリケーションが必要とする最低限のスコープのみを要求することが重要です。
OAuth 2.0 と OpenID Connect の違い
OAuth 2.0は「何にアクセスできるか」(認可)を扱いますが、「誰がアクセスしているか」(認証)は扱いません。OpenID Connect(OIDC)はOAuth 2.0の上に構築された認証レイヤーで、IDトークンを導入することでユーザーの身元確認を可能にしています。「Googleでログイン」「Facebookでログイン」などのソーシャルログイン機能はOIDCに基づいています。
セキュリティ上の考慮事項
- CSRF対策:stateパラメータを使用してクロスサイトリクエストフォージェリを防止
- リダイレクトURIの厳密な検証:オープンリダイレクト攻撃を防ぐため、登録済みURIとの完全一致検証が必要
- トークンの安全な保管:フロントエンドではlocalStorageではなくhttpOnly cookieやセッションストレージを推奨
- トークンの失効管理:不要になったトークンの即座の無効化と、トークン失効エンドポイントの実装
Security Measures
- 01PKCE(Proof Key for Code Exchange)の必須化:すべてのOAuth 2.0クライアント(サーバーサイド・クライアントサイド問わず)でPKCEを使用してください。認可コードの横取り攻撃を防ぎ、特にモバイルアプリやSPAにおけるセキュリティを大幅に向上させます。
- 02アクセストークンの有効期限を短く設定:アクセストークンの有効期限は15分〜1時間に設定し、リフレッシュトークンを使用してトークンのローテーションを行ってください。リフレッシュトークンは1回使用したら無効化するローテーション方式を推奨します。
- 03リダイレクトURIの完全一致検証:認可サーバーで登録されたリダイレクトURIとの完全一致検証(ワイルドカード不使用)を実装してください。オープンリダイレクト脆弱性はトークン窃取の主要な攻撃ベクトルです。
- 04最小権限のスコープ設定:アプリケーションが必要とする最低限のスコープのみを要求してください。過剰なスコープの要求はユーザーの信頼を損なうだけでなく、トークンが漏洩した場合の被害範囲を拡大させます。
- 05stateパラメータによるCSRF対策:認可リクエストには必ず推測不可能なstateパラメータを含め、コールバック時に検証してください。これにより、攻撃者が被害者のブラウザで不正な認可リクエストを実行するCSRF攻撃を防止できます。
- 06トークンの安全な保管と転送:アクセストークンはhttpOnly・Secure属性付きCookieまたはサーバーサイドセッションに保管してください。APIリクエストではAuthorization: Bearerヘッダーでトークンを送信し、URLパラメータへのトークン含有は厳禁です。
Incidents
📋 Facebook OAuthアクセストークン大量漏洩事件(2018年)
2018年9月、Facebookは約5,000万ユーザーのアクセストークンが攻撃者によって窃取されたことを公表しました。攻撃者はFacebookの「プロフィールプレビュー」機能に存在した複数の脆弱性を連鎖的に悪用し、他のユーザーのアクセストークンを取得することに成功しました。
この攻撃では、ビデオアップロード機能のバグと「View As」機能の組み合わせにより、対象ユーザーのOAuthアクセストークンが攻撃者のブラウザに漏洩しました。漏洩したトークンにより、Facebookアカウントだけでなく、Facebook OAuthでログインしていたInstagram、Spotify、Tinderなどのサードパーティサービスへのアクセスも危険にさらされました。Facebookは影響を受けた9,000万アカウントのトークンを強制失効させる対応を行いました。
📋 GitHub OAuthアプリ悪用によるリポジトリ窃取(2022年)
2022年4月、GitHubはHerokuおよびTravis CIに発行されたOAuthアプリトークンが窃取され、数十の組織のプライベートリポジトリに不正アクセスされたことを公表しました。攻撃者は盗まれたOAuthトークンを使用してGitHub APIにアクセスし、npmを含む複数の組織のプライベートリポジトリをダウンロードしました。
この事件はOAuthトークンの広範な権限設定と、サードパーティアプリへのトークン管理の重要性を浮き彫りにしました。GitHubは影響を受けたすべてのOAuthトークンを無効化し、ユーザーに対してサードパーティアプリの権限見直しを呼びかけました。また、OAuthアプリに付与するスコープの最小化と、定期的なトークン監査の必要性が再認識されました。
📋 Booking.com OAuth設定ミスによるアカウント乗っ取り(2023年)
セキュリティ研究者がBooking.comのOAuth実装において、アカウント乗っ取りにつながる重大な設定ミスを発見しました。OAuthフローにおけるリダイレクトURIの検証が不十分であったため、攻撃者はオープンリダイレクト脆弱性を利用して認可コードを自分のサーバーに転送させることが可能でした。
この脆弱性により、攻撃者は被害者のBooking.comアカウントを完全に乗っ取り、予約情報の閲覧・変更、支払い情報へのアクセスが可能な状態でした。この事例はOAuth実装においてリダイレクトURIの厳密な検証がいかに重要であるかを示す典型例です。Booking.comは報告を受けて迅速にパッチを適用し、バグバウンティプログラムを通じて研究者に報奨金を支払いました。