OAuth 2.0は、サードパーティアプリケーションにユーザーの認証情報を共有することなく、そのリソースへの制限付きアクセスを提供する業界標準の認可プロトコルです。このプロトコルは、Webおよびモバイルアプリケーションにおける委任認可のデファクトスタンダードとなり、Google、Facebook、Apple、GitHubなどのプラットフォームで使用されています。IETF RFC 6749(2025)によると、OAuth 2.0は委任されたデータアクセスを必要とするすべてのAPI統合の85%以上で使用されています。
主要ポイント
OAuth 2.0は、IETF RFC 6749で定義された認可プロトコルであり、サードパーティアプリケーションがユーザーのユーザー名とパスワードを開示することなく、そのリソースへの制限付きアクセスを取得できるようにします。このプロトコルは、パスワードモデルの根本的な問題を解決します:パスワードを預けたアプリケーションは、すべてのアカウントデータへの無制限アクセスを取得します。OAuth 2.0は、明示的に制限されたアクセススコープを持つ一時的なトークンを発行することで、このアプローチを置き換えます。
OAuth 2.0のアーキテクチャは委任認可です。ユーザー(Resource Owner)は、仲介者である認可サーバー(Authorization Server)を介して、リソースサーバー(Resource Server)に保存された自分のデータにアクセスすることをアプリケーション(Client)に承認します。認可サーバーはAccess Tokenを発行します。これは、アプリケーションがデータにアクセスするためにリソースサーバーに提示する暗号文字列です。OAuth 2.0とSAMLまたはOpenID Connectの重要な違い:OAuth 2.0は認可タスク(何が許可されるか)を解決し、認証(ユーザーが誰か)は解決しません。認証のためには、OAuth 2.0の上にOpenID Connect(OIDC)プロトコルが構築されています。
このプロトコルはすべての主要プラットフォームでサポートされています。GoogleはGoogle APIs(Gmail、Drive、Calendar)へのアクセスにOAuth 2.0を使用し、FacebookはGraph APIに、AppleはSign in with Apple(ASAuthorizationAppleIDProvider)に、GitHubはリポジトリアクセスに使用しています。モバイル開発のコンテキストでは、OAuth 2.0はサードパーティサービスを統合する標準メカニズムです:ソーシャルネットワーク経由のログイン、クラウドストレージへのアクセス、ユーザーに代わってのコンテンツ公開など。
OAuth 2.0プロトコルは、その相互作用が完全な認可サイクルを形成する4つのロールを定義しています。モバイルアプリケーションでプロトコルを正しく実装するには、各ロールを理解することが不可欠です。
| ロール | 説明 | 例 |
|---|---|---|
| Resource Owner | データの所有者:自分のリソースへのアクセスを許可するユーザー | “Googleでサインイン”をクリックするアプリケーションユーザー |
| Client | 所有者に代わってリソースへのアクセスを要求するアプリケーション | Google Driveへのアクセスが必要なモバイルアプリ |
| Authorization Server | 認証と認可の後にトークンを発行するサーバー | accounts.google.com:Googleの認可サーバー |
| Resource Server | トークンによって保護されたリソースへのアクセスを提供するAPI | www.googleapis.com:Google Drive APIのリソースサーバー |
プロトコルの主要なエンティティは、Access Token、Refresh Token、Authorization Codeです。Access Tokenは短期間のトークン(通常15~60分)で、データリクエストごとにリソースサーバーに提示されます。Refresh Tokenは長期間のトークン(数日または数週間)で、ユーザーが再ログインすることなく新しいAccess Tokenを取得するために使用されます。Authorization Codeは一時的なコードで、ユーザーの承認後に発行され、Access TokenおよびRefresh Tokenと交換されます。
OAuth 2.0は、いくつかのGrant Types(トークン取得シナリオ)を定義しており、それぞれが特定のクライアントタイプとセキュリティコンテキスト向けに設計されています。モバイルアプリケーションで認可を設計する際、適切なGrant Typeを選択することは重要なアーキテクチャ上の決定です。
主なGrant Typesは以下の通りです:Authorization Code(サーバーコンポーネントを持つモバイルおよびWebアプリケーションに最も安全)、PKCE付きAuthorization Code(Proof Key for Code Exchange:サーバーバックエンドなしのモバイルおよびSPAアプリケーション向け)、Client Credentials(ユーザー関与なしのサーバー間認証用)、Resource Owner Password Credentials(非推奨:パスワードを直接送信)。OAuth Security BCP(RFC 9700)の推奨に従い、PKCEはパブリッククライアント(モバイルアプリケーション、SPA)に必須の拡張機能です。
PKCE対応Authorization Code Flowは、ネイティブモバイルアプリケーションに推奨されるOAuth 2.0構成です。PKCE(Proof Key for Code Exchange)は、authorization codeインターセプト攻撃を防ぐ追加の保護層を追加します。プロトコルはIETF RFC 7636で説明されています。
手順の順序:(1)クライアントはランダムなcode_verifierを生成します(予約されていない文字のみを使用した43~128文字の文字列)、(2)クライアントはcode_challenge = SHA-256(code_verifier)を計算します、(3)クライアントはcode_challengeを渡してAuthorization Serverでユーザー認可のためにブラウザを開きます、(4)認可成功後、サーバーはカスタムURIスキーム(アプリのディープリンク)を介してアプリケーションにauthorization codeを返します、(5)クライアントはauthorization code + code_verifierをサーバーに送信します、(6)サーバーはSHA-256(code_verifier) === code_challengeを検証し、Access Token + Refresh Tokenを発行します。
PKCEの利点:攻撃者がURIスキームでauthorization codeをインターセプトしたとしても、正当なクライアントのみが知るcode_verifierなしではトークンと交換できません。モバイルアプリケーションでは、ブラウザを開くためにChrome Custom Tabs(Android)またはASWebAuthenticationSession(iOS)を使用する必要があります。これにより、システムブラウザがアプリケーションのメモリからcode_verifierにアクセスできないことが保証されます。
AppAuthは、IETF推奨のネイティブアプリケーション向けOAuth 2.0およびOpenID Connectのリファレンス実装です。このライブラリは、PKCE、Chrome Custom Tabs、authorization codeを返すためのカスタムURIスキーム、自動トークン更新をサポートしています。Android用AppAuthは、依存関係`net.openid:appauth:0.11.1`で利用可能です。
val serviceConfig = AuthorizationServiceConfiguration.fromUrl(
Uri.parse("https://accounts.google.com/.well-known/openid-configuration")
)
val request = AuthorizationRequest.Builder(
serviceConfig,
"CLIENT_ID.apps.googleusercontent.com",
ResponseTypeValues.CODE,
Uri.parse("com.example.app:/oauth2callback")
)
.setScope("openid profile email")
.setCodeVerifier(
CodeVerifierUtil.generateRandomCodeVerifier()
)
.build()
val authService = AuthorizationService(context)
val intent = authService.getAuthorizationRequestIntent(request)
// 認可用Chrome Custom Tabを起動
startActivityForResult(intent, REQUEST_CODE_AUTH)
authorization code(onActivityResult)を受信した後、アプリケーションはTokenRequestを介してAccess TokenとRefresh Tokenと交換します。トークンはEncryptedSharedPreferences(Android Security Crypto)による暗号化付きでSharedPreferencesに保存されます。Refresh TokenはKeyStore(ハードウェアベースのキーストアで、他のアプリケーションからアクセス不可)に保存する必要があります。Access Tokenが期限切れになるたびに、アプリケーションはRefresh Tokenを使用して新しいトークンを取得します。ユーザーは再認証する必要はありません。
// authorization codeをトークンと交換
val data = intent?.data ?: return
val resp = AuthorizationResponse.fromIntent(data)
val exchangeReq = resp?.createTokenExchangeRequest()
?: return
authService.performTokenRequest(
exchangeReq,
ClientAuthentication.none()
) { tokenResp, ex ->
if (tokenResp != null) {
// Access TokenとRefresh Tokenを受信しました
val accessToken = tokenResp.accessToken
val refreshToken = tokenResp.refreshToken
// EncryptedSharedPreferencesに保存
saveTokens(accessToken, refreshToken)
}
}
上記のコードは、PKCEを使用した完全なOAuth 2.0フローを示しています:OpenID Connect Discoveryによるサーバー構成の作成、code_verifier付き認可リクエストの生成、Chrome Custom Tabの起動、カスタムURIスキームによるauthorization codeの受信、Token Requestによるトークンとのコード交換。Access Tokenの期限切れ処理は重要です:Resource ServerからHTTP 401応答を受信した場合、アプリケーションはRefresh Tokenを使用して新しいAccess Tokenを取得し、リクエストを再実行する必要があります。
OAuth 2.0は、多くの攻撃ベクトルを持つ複雑なプロトコルです。IETF Security BCP(RFC 9700)は、OAuth 2.0の脆弱性の20以上のクラスを説明しています。モバイルアプリケーションにとって最も重要なのは:カスタムURIスキームによるauthorization codeのインターセプト、コールバックエンドポイントへのCSRF攻撃、安全でないストレージからのRefresh Tokenの盗難、インテントインターセプトによるクライアントのなりすましです。
これらの攻撃からの保護には、必須の対策が含まれます:(1)S256 code_challengeによるPKCE:URIスキームがインターセプトされてもauthorization codeのインターセプトを防止します。(2)CSRFを防ぐためのnonceまたはstateパラメータの使用:サーバーはauthorization codeが元のリクエストと一致することを検証します。(3)Refresh TokenをKeyStore(Android)またはKeychain(iOS)のみに保存:SharedPreferencesやUserDefaultsには保存しません。(4)トランスポート層でのMITMからの保護のためのCertificate Pinning付きTLSの使用。(5)redirect_uriの検証:認可サーバーは登録されたURIとの一致を厳密に検証する必要があります。
IETFからの追加推奨事項:モバイルアプリケーションは、セキュリティ監査を受けたAppAuthまたは類似のライブラリを使用する必要があります。OAuthにWebViewを使用しないでください(WebViewはメインアプリケーションからデータを分離しません)。自動Refresh Tokenローテーションを実装してください(各Refresh Tokenは1回のみ使用可能)。AndroidではTrustManager、iOSではURLSessionを介してCertificate Pinningを追加してください。OpenID Connect Discovery(well-knownエンドポイント)は、認可サーバーの正しいエンドポイントを自動的に決定し、フィッシングページへのリダイレクトを回避するのに役立ちます。
よくある質問
OAuth 2.0は認可プロトコル(何をすることを許可されるか?)であり、OpenID Connect(OIDC)は認証プロトコル(ユーザーは誰か?)です。OIDCはOAuth 2.0の上に構築され、ID Token(ユーザーのID情報を含むJWTトークン)を追加します。OAuth 2.0はAccess Tokenを提供し、OIDCはID TokenとUserInfoエンドポイントを補完してユーザープロファイルを取得します。
Bearer Tokenは、HTTPヘッダーAuthorization:Bearerで提示されるAccess Tokenです。その危険性は、トークンを保持する誰もがリソースにアクセスできることです:トークンはクライアントにバインドされていません。したがって、Bearer TokenはTLS(HTTPS)を介してのみ送信され、短い有効期間(15~60分)を持ち、ログやURLパラメータに決して保存してはなりません。
モバイルアプリケーションはclient_secretを持たないパブリッククライアントです(APK/IPAで秘密を保護できません)。PKCEがない場合、攻撃者はカスタムURIスキーム(例:malformed://callback?code=ABC)を介してauthorization codeをインターセプトし、トークンと交換できます。PKCEはアプリケーションのみが知るcode_verifierを追加し、インターセプトされたコードを無効にします。
典型的なAccess Tokenの有効期間は15~60分です(認可サーバーで設定可能)。Resource Serverへの各HTTPリクエストで応答がチェックされます:コードが401の場合、アプリケーションはRefresh Token Flowをトリガーして新しいAccess Tokenを取得します。Refresh Tokenの有効期間は、プロバイダーのセキュリティポリシーに応じて24時間から数ヶ月です。Refresh Tokenが変更されると、古いものは無効になります。
いいえ:IETF Security BCP(RFC 9700)は、モバイルアプリケーションでのOAuth 2.0のWebView使用を禁止しています。WebViewはメインアプリケーションからクッキーとデータを分離しないため、アプリケーションがユーザーの認証情報をインターセプトできます。WebViewの代わりに、Chrome Custom Tabs(Android)またはASWebAuthenticationSession(iOS)を使用してください:アプリケーションから分離されたシステムブラウザコンポーネントです。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。