iOS およびデスクトップ アプリ用 OAuth 2.0

このドキュメントでは、スマートフォン、タブレット、パソコンなどのデバイスにインストールされたアプリケーションが、Google の OAuth 2.0 エンドポイントを使用して Google API へのアクセスを認可する方法について説明します。

OAuth 2.0 では、ユーザー名やパスワードなどの情報を秘密にしたまま、ユーザーが特定のデータをアプリケーションと共有できます。たとえば、アプリケーションは OAuth 2.0 を使用して、Google ドライブにファイルを保存する権限をユーザーから取得できます。

インストール済みのアプリは個々のデバイスに配布されるため、これらのアプリはシークレットを保持できないと想定されます。ユーザーがアプリを使用しているとき、またはアプリがバックグラウンドで実行されているときに、Google API にアクセスできます。

この認可フローは、ウェブサーバー アプリケーションで使用されるフローに似ています。主な違いは、インストール済みのアプリでは、システム ブラウザを開き、Google の認可サーバーからのレスポンスを処理するためにローカル リダイレクト URI を指定する必要があることです。

ライブラリとサンプル

iOS アプリの場合は、最新バージョンの Sign In With Google iOS SDK を使用することをおすすめします。SDK はユーザー認証を処理するため、このガイドで説明する下位レベルのプロトコルよりも簡単に実装できます。

システム ブラウザをサポートしていないデバイスや、入力機能が制限されているデバイス(テレビ、ゲーム機、カメラ、プリンタなど)で実行されるアプリについては、テレビおよびデバイス用の OAuth 2.0 またはテレビおよび入力機能が制限されたデバイスでのログインをご覧ください。

前提条件

プロジェクトでAPI を有効にする

Google API を呼び出すアプリケーションは、API Console でそれらの API を有効にする必要があります。

プロジェクトで API を有効にするには:

  1. Google API Console で API ライブラリを開きます。
  2. プロンプトが表示されたら、プロジェクトのいずれかを選択するか、新しいプロジェクトを作成します。
  3. API ライブラリには、利用可能なすべての API がプロダクト ファミリーと人気度に応じてグループ化されて表示されます。有効にする API がリストで見当たらない場合は、検索して見つけるか、その API が属するプロダクト ファミリーの [すべて表示] をクリックします。
  4. 有効にする API を選択し、[有効にする] ボタンをクリックします。
  5. プロンプトが表示されたら、請求機能を有効にします。
  6. プロンプトが表示されたら、API の利用規約を確認し、同意します。

承認認証情報を作成する

OAuth 2.0 を使用して Google API にアクセスするアプリケーションには、Google の OAuth 2.0 サーバーにアプリケーションを識別させる認証情報が必要です。次の手順では、プロジェクトの認証情報を作成する方法について説明します。アプリケーションは、この認証情報を使用して、そのプロジェクトで有効にした API にアクセスできます。

  1. [クライアント] ページに移動します。
  2. [クライアントの作成] をクリックします。
  3. 以降のセクションでは、Google の認可サーバーがサポートするクライアント タイプについて説明します。アプリケーションに推奨されるクライアント タイプを選択し、OAuth クライアントに名前を付けて、フォームの他のフィールドを適切に設定します。
iOS
  1. [iOS] アプリケーションの種類を選択します。
  2. OAuth クライアントの名前を入力します。この名前は、プロジェクトのクライアント ページに表示され、クライアントを識別するために使用されます。
  3. アプリのバンドル ID を入力します。バンドル ID は、アプリの情報プロパティ リスト リソース ファイル(info.plist)の CFBundleIdentifier キーの値です。この値は通常、Xcode プロジェクト エディタの [General] ペインまたは [Signing & Capabilities] ペインに表示されます。バンドル ID は、Apple の App Store Connect サイトのアプリの [App Information] ページの [General Information] セクションにも表示されます。

    アプリに正しいバンドル ID を使用していることを確認します。App Check 機能を使用している場合は、バンドル ID を変更できません。

  4. (省略可)

    アプリが Apple の App Store で公開されている場合は、アプリの App Store ID を入力します。ストア ID は、Apple App Store のすべての URL に含まれる数字の文字列です。

    1. iOS または iPadOS デバイスで Apple App Store アプリを開きます。
    2. 自分のアプリを探します。
    3. 共有ボタン(四角形と上向き矢印の記号)を選択します。
    4. [リンクをコピー] を選択します。
    5. テキスト エディタにリンクを貼り付けます。アプリストア ID は URL の最後の部分です。

      例: https://apps.apple.com/app/google/id284815942

  5. (省略可)

    チーム ID を入力します。詳しくは、Apple デベロッパー アカウントのドキュメントのチーム ID を確認するをご覧ください。

    注: クライアントで App Check を有効にする場合は、[Team ID] フィールドが必須です。
  6. (省略可)

    iOS アプリで App Check を有効にします。App Check を有効にすると、Apple の App Attest サービスを使用して、OAuth クライアントから送信された OAuth 2.0 リクエストが正規のものであり、アプリから送信されたものであることを確認します。これにより、アプリのなりすましのリスクを軽減できます。iOS アプリで App Check を有効にする方法の詳細。

  7. [作成] をクリックします。
パソコン
  1. [デスクトップ アプリ] アプリケーションの種類を選択します。
  2. [名前] フィールドに、OAuth クライアントの名前を入力します。この名前は、プロジェクトのクライアント ページに表示され、クライアントを識別するために使用されます。
  3. [作成] をクリックします。

アクセス スコープを特定する

スコープを使用すると、アプリケーションは必要なリソースへのアクセスのみをリクエストできます。また、ユーザーはアプリケーションに付与するアクセス量を制御できます。したがって、リクエストするスコープの数とユーザーの同意を得られる可能性は、反比例の関係にある可能性があります。

OAuth 2.0 認可の実装を開始する前に、アプリがアクセス許可を必要とするスコープを特定することをおすすめします。

OAuth 2.0 API スコープのドキュメントには、Google API へのアクセスに使用できるスコープの完全なリストが記載されています。

OAuth 2.0 アクセス トークンの取得

次の手順は、アプリケーションが Google の OAuth 2.0 サーバーとやり取りして、ユーザーの代わりに API リクエストを実行することに対するユーザーの同意を得る方法を示しています。ユーザーの承認が必要な Google API リクエストを実行するには、アプリがその同意を得ている必要があります。

ステップ 1: コード検証ツールとチャレンジを生成する

Google は、インストール済みアプリのフローのセキュリティを強化するために、Proof Key for Code Exchange(PKCE)プロトコルをサポートしています。一意のコード検証ツールが認可リクエストごとに作成され、その変換された値(「code_challenge」と呼ばれる)が認可サーバーに送信されて認可コードが取得されます。

コード検証ツールを作成する

code_verifier は、予約されていない文字 [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" を使用した高エントロピーの暗号化ランダム文字列です。最小長は 43 文字、最大長は 128 文字です。

コード検証ツールには、値を推測することが不可能なほど十分なエントロピーが必要です。

コード チャレンジを作成する

コード チャレンジを作成する方法は 2 つあります。

コード チャレンジの生成方法
S256(推奨) コード チャレンジは、コード検証ツールの Base64URL(パディングなし)でエンコードされた SHA256 ハッシュです。
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
plain コード チャレンジは、上記で生成されたコード検証ツールと同じ値です。
code_challenge = code_verifier

ステップ 2: Google の OAuth 2.0 サーバーにリクエストを送信する

ユーザーの認可を取得するには、https://accounts.google.com/o/oauth2/v2/auth で Google の認可サーバーにリクエストを送信します。このエンドポイントは、アクティブなセッションの検索、ユーザーの認証、ユーザーの同意の取得を処理します。エンドポイントには SSL 経由でのみアクセスでき、HTTP(非 SSL)接続は拒否されます。

認可サーバーは、インストール済みアプリケーションに対して次のクエリ文字列パラメータをサポートしています。

パラメータ
client_id 必須

アプリケーションのクライアント ID。この値は、Cloud コンソールの [クライアント] ページで確認できます。

redirect_uri 必須

Google の認証サーバーがアプリにレスポンスを送信する方法を指定します。インストール済みのアプリにはいくつかのリダイレクト オプションが用意されており、特定のリダイレクト方法を念頭に置いて認証情報を設定します。

この値は、クライアントの Cloud コンソールのクライアント ページで構成した OAuth 2.0 クライアントの承認済みリダイレクト URI のいずれかと完全に一致する必要があります。この値が承認済みの URI と一致しない場合、redirect_uri_mismatch エラーが発生します。

次の表に、各メソッドに適した redirect_uri パラメータ値を示します。

redirect_uri 個の値
カスタム URI スキーム com.example.app:redirect_uri_path

または

com.googleusercontent.apps.123:redirect_uri_path
  • com.example.app は、管理下にあるドメインの逆引き DNS 表記です。カスタム スキームには、有効な期間を含める必要があります。
  • com.googleusercontent.apps.123 は、クライアント ID の逆引き DNS 表記です。
  • redirect_uri_path は、/oauth2redirect などのオプションのパス コンポーネントです。パスは、通常の HTTP URL とは異なり、1 つのスラッシュで始まる必要があります。
ループバック IP アドレス http://127.0.0.1:port または http://[::1]:port

プラットフォームに関連するループバック IP アドレスをクエリし、ランダムな使用可能なポートで HTTP リスナーを起動します。port は、アプリがリッスンする実際のポート番号に置き換えます。

モバイルアプリでのループバック IP アドレス リダイレクト オプションのサポートは 非推奨になりました。

response_type 必須

Google OAuth 2.0 エンドポイントが認証コードを返すかどうかを決定します。

インストール済みアプリケーションのパラメータ値を code に設定します。

scope 必須

アプリケーションがユーザーに代わってアクセスできるリソースを識別するスコープのスペース区切りのリスト。これらの値は、Google がユーザーに表示する同意画面に反映されます。

スコープを使用すると、アプリケーションは必要なリソースへのアクセスのみをリクエストできます。また、ユーザーはアプリケーションに付与するアクセス量を制御できます。したがって、リクエストするスコープの数とユーザーの同意を得られる可能性は反比例の関係にあります。

code_challenge 推奨

認可コードの交換時にサーバーサイド チャレンジとして使用される、エンコードされた code_verifier を指定します。詳細については、コード チャレンジを作成するをご覧ください。

code_challenge_method 推奨

認証コードの交換時に使用される code_verifier のエンコードに使用されたメソッドを指定します。このパラメータは、code_challenge パラメータと組み合わせて使用する必要があります。code_challenge を含むリクエストに code_challenge_method が存在しない場合、 の値はデフォルトで plain になります。このパラメータでサポートされている値は、S256 または plain のみです。

state 推奨

アプリケーションが認可リクエストと認可サーバーのレスポンスの間で状態を維持するために使用する任意の文字列値を指定します。サーバーは、ユーザーがアプリケーションのアクセス リクエストを承認または拒否した後、redirect_uri の URL フラグメント識別子(#)で name=value ペアとして送信した正確な値を返します。

このパラメータは、ユーザーをアプリケーション内の正しいリソースに誘導する、ノンスを送信する、クロスサイト リクエスト フォージェリを軽減するなど、いくつかの目的で使用できます。redirect_uri は推測される可能性があるため、state 値を使用すると、受信接続が認証リクエストの結果であるという確実性が高まります。ランダムな文字列を生成するか、Cookie のハッシュまたはクライアントの状態をキャプチャする別の値をエンコードすると、レスポンスを検証して、リクエストとレスポンスが同じブラウザで発生したことを確認し、クロスサイト リクエスト フォージェリなどの攻撃から保護できます。state トークンを作成して確認する方法の例については、OpenID Connect のドキュメントをご覧ください。

login_hint 省略可

アプリケーションが認証を試みるユーザーを把握している場合は、このパラメータを使用して Google 認証サーバーにヒントを提供できます。サーバーは、ログイン フォームのメール フィールドに事前入力するか、適切なマルチログイン セッションを選択することで、ログインフローを簡素化するためにヒントを使用します。

パラメータ値を、ユーザーの Google ID に相当するメールアドレスまたは sub 識別子に設定します。

認証 URL の例

以下のタブに、さまざまなリダイレクト URI オプションの認証 URL の例を示します。

URL は、redirect_uri パラメータの値を除いて同じです。URL には、必須の response_type パラメータと client_id パラメータ、およびオプションの state パラメータも含まれています。各 URL には、読みやすくするために改行とスペースが含まれています。

カスタム URI スキーム

https://accounts.google.com/o/oauth2/v2/auth?
 scope=email%20profile&
 response_type=code&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2.example.com%2Ftoken&
 redirect_uri=com.example.app%3A/oauth2redirect&
 client_id=client_id

ループバック IP アドレス

https://accounts.google.com/o/oauth2/v2/auth?
 scope=email%20profile&
 response_type=code&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2.example.com%2Ftoken&
 redirect_uri=http%3A//127.0.0.1%3A9004&
 client_id=client_id

ステップ 3: Google がユーザーに同意を求める

このステップでは、ユーザーがアプリケーションにリクエストされたアクセス権を付与するかどうかを決定します。この段階で、Google は同意ウィンドウを表示します。このウィンドウには、アプリケーションの名前、ユーザーの認証情報を使用してアクセス許可をリクエストしている Google API サービス、付与されるアクセス スコープの概要が表示されます。ユーザーは、アプリケーションからリクエストされた 1 つ以上のスコープへのアクセス権の付与に同意するか、リクエストを拒否できます。

この段階では、アプリケーションは何もする必要はありません。Google の OAuth 2.0 サーバーからアクセスが許可されたかどうかを示すレスポンスが返されるのを待ちます。このレスポンスについては、次のステップで説明します。

エラー

Google の OAuth 2.0 認可エンドポイントへのリクエストで、想定される認証フローと認可フローではなく、ユーザー向けのエラー メッセージが表示されることがあります。一般的なエラーコードと推奨される解決策は次のとおりです。

admin_policy_enforced

Google Workspace 管理者のポリシーにより、Google アカウントはリクエストされた 1 つ以上のスコープを承認できません。管理者が OAuth クライアント ID にアクセスを明示的に付与するまで、すべてのスコープ、または機密スコープと制限付きスコープへのアクセスを制限する方法については、Google Workspace 管理者向けのヘルプ記事 Google Workspace のデータにアクセスできるサードパーティ製アプリと内部アプリを制御するをご覧ください。

disallowed_useragent

認可エンドポイントが、Google の OAuth 2.0 ポリシーで許可されていない埋め込みユーザー エージェント内に表示されている。

iOS と macOS のデベロッパーは、WKWebView で承認リクエストを開くときに、このエラーが発生することがあります。デベロッパーは、代わりに Google ログイン for iOS や OpenID Foundation の AppAuth for iOS などの iOS ライブラリを使用する必要があります。

ウェブ デベロッパーは、iOS または macOS アプリが埋め込みユーザー エージェントで一般的なウェブリンクを開き、ユーザーがサイトから Google の OAuth 2.0 認可エンドポイントに移動したときに、このエラーに遭遇することがあります。デベロッパーは、ユニバーサル リンク ハンドラとデフォルトのブラウザアプリの両方を含む、オペレーティング システムのデフォルトのリンクハンドラで一般的なリンクを開けるようにする必要があります。SFSafariViewController ライブラリもサポートされているオプションです。

org_internal

リクエスト内の OAuth クライアント ID は、特定の Google Cloud 組織内の Google アカウントへのアクセスを制限するプロジェクトの一部です。この構成オプションの詳細については、OAuth 同意画面の設定に関するヘルプ記事のユーザータイプのセクションをご覧ください。

deleted_client

リクエストに使用されている OAuth クライアントが削除されています。削除は、手動で行うことも、未使用のクライアント の場合は自動的に行うこともできます。削除したクライアントは、削除後 30 日以内であれば復元できます。 詳細 。

invalid_grant

コード検証ツールとチャレンジを使用している場合、code_callenge パラメータが無効であるか、指定されていません。code_challenge パラメータが正しく設定されていることを確認します。

アクセス トークンを更新するときに、トークンの有効期限が切れているか、無効になっている可能性があります。 ユーザーを再度認証し、新しいトークンを取得するためのユーザーの同意を求めます。このエラーが引き続き表示される場合は、アプリケーションが正しく構成されていること、リクエストで正しいトークンとパラメータを使用していることを確認してください。それ以外の場合は、ユーザー アカウントが削除または無効になっている可能性があります。

redirect_uri_mismatch

認可リクエストで渡された redirect_uri が、OAuth クライアント ID の承認済みリダイレクト URI と一致しません。Google Cloud コンソールの [クライアント] ページで、承認済みのリダイレクト URI を確認します。

渡された redirect_uri がクライアント タイプに対して無効である可能性があります。

redirect_uri パラメータは、非推奨となり、サポートが終了した OAuth 帯域外(OOB)フローを参照している可能性があります。統合を更新するには、移行ガイドをご覧ください。

invalid_request

リクエストに問題がありました。これには、次のようなさまざまな理由が考えられます。

  • リクエストの形式が正しくありませんでした
  • リクエストに必須パラメータが含まれていませんでした
  • リクエストで、Google がサポートしていない認証方法が使用されています。OAuth 統合で推奨される統合方法が使用されていることを確認する
  • リダイレクト URI に、サポートされていないカスタム スキームが使用されました。「 カスタム URI スキームは Android アプリまたは Chrome アプリではサポートされていません」というエラー メッセージが表示された場合は、カスタム URI スキームの代替手段について詳細をご確認ください。

ステップ 4: OAuth 2.0 サーバーのレスポンスを処理する

アプリケーションが認可レスポンスを受け取る方法は、使用するリダイレクト URI スキームによって異なります。スキームに関係なく、レスポンスには認証コード(code)またはエラー(error)が含まれます。たとえば、error=access_denied は、ユーザーがリクエストを拒否したことを示します。

ユーザーがアプリケーションにアクセスを許可すると、次のステップで説明するように、認証コードをアクセス トークンおよび更新トークンと交換できます。

ステップ 5: 認証コードを更新トークンとアクセス トークンに交換する

認証コードをアクセス トークンと交換するには、https://oauth2.googleapis.com/token エンドポイントを呼び出し、次のパラメータを設定します。

フィールド
client_id Cloud コンソールの [クライアント] ページから取得したクライアント ID。
client_secret 省略可

Cloud コンソールのクライアント ページから取得したクライアント シークレット。

code 最初のリクエストから返された認証コード。
code_verifier ステップ 1 で作成したコード検証ツール。
grant_type OAuth 2.0 仕様で定義されているように、このフィールドの値は authorization_code に設定する必要があります。
redirect_uri Cloud コンソールの [クライアント] ページで、指定された client_id のプロジェクトに一覧表示されているリダイレクト URI の 1 つ。

DPoP の使用は任意ですが、セキュリティを強化するため、使用することをおすすめします。DPoP のセキュリティは、秘密鍵が 1 台のデバイスに制限されていることに依存しています。TPM、Secure Enclave、その他のハードウェア格納型キーストアなどを使用して、デバイス外にコピーできない方法で保存することをおすすめします。DPoP を使用するには、アプリケーションがトークン エンドポイントへのリクエストごとに新しい一意の DPoP 証明 JWT を生成し、HTTP リクエスト ヘッダーとして追加する必要があります。

ヘッダー 必須 説明
DPoP 省略可 DPoP 証明は、秘密鍵の所有を証明する JWT です。これはパラメータではなくヘッダーです。指定すると、返されたトークンがこの鍵にバインドされます。リクエストごとに新しい一意の証明を生成する必要があります。また、リクエストに一致する htm(HTTP メソッド)クレームと htu(HTTP URI)クレームを含める必要があります。

次のスニペットは、リクエストの例を示しています。

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik\
 VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR\
 nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE\
 QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj\
 oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia\
 WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg\
 4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
redirect_uri=http://127.0.0.1:9004&
grant_type=authorization_code

DPoP 証明を作成する

次の手順では、コマンドラインから OpenSSL を使用して DPoP 証明を作成する方法について説明します。

  1. EC P-256 鍵ペアを生成します。
    openssl ecparam -name prime256v1 -genkey -noout -out dpop_private.pem
    openssl ec -in dpop_private.pem -pubout -out dpop_public.pem
  2. DPoP ヘッダーを作成します。

    ヘッダーには、typ、alg、jwk(公開鍵)のクレームを含める必要があります。x と y の値は、EC 公開鍵の Base64Url でエンコードされた座標です。この JSON を Base64Url エンコードします。

    {
      "typ":"dpop+jwt",
      "alg":"ES256",
      "jwk": {
        "kty":"EC",
        "x":"YOUR_PUBLIC_KEY_X",
        "y":"YOUR_PUBLIC_KEY_Y",
        "crv":"P-256"
      }
    }
  3. DPoP ペイロードを作成する:

    ペイロードには、jti(リクエストの固有識別子)、htm(HTTP メソッド、例: POST)、htu(HTTP URI、例: https://oauth2.googleapis.com/token)、iat(発行時刻)を含める必要があります。前のリクエストに対するレスポンスの DPoP-Nonce ヘッダーでサーバーからノンスを受け取った場合は、そのノンス値を nonce クレームに含める必要があります。nonce クレームは、認証コード交換では省略可能であり、以前に DPoP-Nonce ヘッダーを受信した場合にのみ使用されます。この JSON を Base64Url エンコードします。

    {
      "jti":"JTI_VALUE",
      "htm":"POST",
      "htu":"https://oauth2.googleapis.com/token",
      "iat":YOUR_JWT_ISSUED_TIME,
      "nonce":"SERVER_PROVIDED_NONCE"
    }

    jti の値は、エクスチェンジのタイプによって異なります。

    • 認証コード交換の場合、jti は認証コードの Base64Url エンコードされた SHA256 ハッシュ("jti":"BASE64URL(SHA256(AUTHORIZATION_CODE))")である必要があります。
    • 更新トークンの交換の場合、jti はリクエストごとに一意の識別子("jti":"YOUR_UNIQUE_PER_REQUEST_IDENTIFIER")にする必要があります。
  4. 証明に署名する:

    エンコードされたヘッダーとペイロードをピリオド(.)で連結し、ES256 を使用して秘密鍵で結果に署名します。JWS では、署名が未加工の R | S 連結形式(P-256 の場合は 64 バイト)である必要があります。OpenSSL を直接使用する場合は、デフォルトの ASN.1 DER エンコード署名をこの未加工形式に変換する必要があります。

交換が成功すると、トークンを含む 200 OK レスポンスが返されます。交換時に有効な DPoP 署名が使用された場合、Google から返される更新トークンは鍵に DPoP バインドされますが、アクセス トークンは DPoP バインドされません。アクセス トークンは、DPoP ではなく Bearer の token_type を保持します。また、Google はレスポンスで DPoP-Nonce HTTP ヘッダーを返します。 クライアントは、このノンスをキャッシュに保存し、後続のリクエスト(更新トークンを新しいアクセス トークンと交換する場合や、DPoP で保護された API を呼び出す場合など)で DPoP 証明の nonce クレームに含める必要があります。この早期発行のノンスを使用すると、次のリクエストで余分な往復エラー(use_dpop_nonce)を回避できます。

DPoP バインド更新トークンを使用して行われたトークン交換リクエストには、DPoP 認証を含める必要があります。

DPoP ヘッダーが想定どおりに存在しない場合、無効な場合、または証明がトークンにバインドされている鍵とは異なる鍵を使用している場合、交換は失敗します。このような場合、サーバーは 400 Bad Request エラーを返します。DPoP 証明に一致しない htm クレームまたは htu クレーム、期限切れの iat、再利用された jti、または無効な署名がある場合、Google は invalid_dpop_proof エラーコードを返します。更新トークンの交換時など、DPoP ノンスが必要な場合に、DPoP 証明に nonce クレームがないか、ノンス値がサーバーで受け入れられない(期限切れ、すでに使用されている、正しくないなど)場合、Google は use_dpop_nonce エラーコードを返します。また、後続のリクエストで使用できる新しいノンスを含む DPoP-Nonce HTTP ヘッダーも返します。その他のエラーでは invalid_grant が返されることがあります。

Google は、有効期間の短いアクセス トークンと更新トークンを含む JSON オブジェクトを返すことで、このリクエストに応答します。

レスポンスには、次のフィールドが含まれます。

フィールド
access_token Google API リクエストを承認するためにアプリケーションが送信するトークン。
expires_in アクセス トークンの残りの有効期間(秒単位)。
id_token 注: このプロパティは、リクエストに ID スコープ(openid、profile、email など)が含まれている場合にのみ返されます。この値は、ユーザーに関するデジタル署名された ID 情報を含む JSON Web Token(JWT)です。
refresh_token 新しいアクセス トークンの取得に使用できるトークン。更新トークンは、ユーザーがアクセスを取り消すか、更新トークンの有効期限が切れるまで有効です。DPoP が使用された場合、更新トークンは DPoP 署名の署名に使用された秘密鍵にバインドされます。インストール済みアプリケーションの場合、更新トークンは常に返されます。
refresh_token_expires_in 更新トークンの残りの有効期間(秒単位)。この値は、ユーザーが時間ベースのアクセスを許可した場合にのみ設定されます。
scope access_token によって付与されるアクセス スコープ。スペース区切りの大文字と小文字を区別する文字列のリストとして表されます。
token_type 返されるトークンのタイプ。この値は、DPoP が使用されている場合でも常に Bearer です。

次のスニペットは、DPoP が使用されている場合の成功したレスポンス ヘッダーと本文の例を示しています。

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
DPoP-Nonce: AN3XwJjZsjnb0ZuWkRlek8QU7wY-Zhf-5IP6tO0tORz0KgtDT1Bo8FX-w4nz3r5lnepI

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "token_type": "Bearer",
  "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly",
  "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

ステップ 6: ユーザーが付与したスコープを確認する

複数の権限(スコープ)をリクエストした場合、ユーザーがアプリにすべての権限へのアクセスを許可しないことがあります。アプリは、実際に付与されたスコープを確認し、一部の権限が拒否された状況を適切に処理する必要があります。通常は、拒否されたスコープに依存する機能を無効にします。

例外もございます。ドメイン全体の権限の委任が設定されている Google Workspace Enterprise アプリ、または信頼できるとしてマークされているアプリでは、詳細な権限の同意画面が省略されます。これらのアプリでは、詳細な権限の同意画面は表示されません。代わりに、アプリはリクエストされたすべてのスコープを受け取るか、まったく受け取らないかのいずれかになります。

詳細については、詳細な権限を処理する方法をご覧ください。

ユーザーが特定のスコープへのアクセスをアプリケーションに許可しているかどうかを確認するには、アクセス トークン レスポンスの scope フィールドを調べます。アクセス トークンによって付与されるアクセス スコープ。スペース区切りの大文字と小文字を区別する文字列のリストとして表されます。

たとえば、次のアクセス トークン レスポンスの例は、ユーザーがアプリケーションに読み取り専用のドライブ アクティビティとカレンダーの予定の権限へのアクセスを許可したことを示しています。

  {
    "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
    "expires_in": 3920,
    "token_type": "Bearer",
    "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly",
    "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
  }

Google API を呼び出す

アプリケーションがアクセス トークンを取得すると、API で必要なアクセス スコープが付与されている場合、そのトークンを使用して、特定のユーザー アカウントに代わって Google API を呼び出すことができます。これを行うには、access_token クエリ パラメータまたは Authorization HTTP ヘッダーの Bearer 値のいずれかを含めて、API へのリクエストにアクセス トークンを含めます。クエリ文字列はサーバーログに表示される傾向があるため、可能な場合は HTTP ヘッダーを使用することをおすすめします。ほとんどの場合、クライアント ライブラリを使用して Google API への呼び出しを設定できます(Drive Files API を呼び出す場合など)。

OAuth 2.0 Playground で、すべての Google API を試して、そのスコープを確認できます。

HTTP GET の例

Authorization: Bearer HTTP ヘッダーを使用した drive.files エンドポイント(Drive Files API)の呼び出しは、次のようになります。独自のアクセス トークンを指定する必要があります。

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

access_token クエリ文字列パラメータを使用して、認証済みユーザーに対して同じ API を呼び出す例を次に示します。

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

curl の例

これらのコマンドは、curl コマンドライン アプリケーションでテストできます。HTTP ヘッダー オプション(推奨)を使用した例を次に示します。

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

または、クエリ文字列パラメータ オプションを使用します。

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

アクセス トークンを更新する

アクセス トークンは定期的に期限が切れ、関連する API リクエストに対して無効な認証情報になります。トークンに関連付けられたスコープへのオフライン アクセスをリクエストした場合は、ユーザーに権限を求めることなく(ユーザーが不在の場合を含めて)アクセス トークンを更新できます。

アクセス トークンを更新するには、アプリケーションから Google の認可サーバー(https://oauth2.googleapis.com/token)に HTTPS POST リクエストを送信します。このリクエストの本文には、次のパラメータが含まれます。

名前 値
client_id API Console から取得したクライアント ID。
client_secret 省略可

API Console から取得したクライアント シークレット。 (client_secret は、Android、iOS、Chrome アプリケーションとして登録されたクライアントからのリクエストには適用されません)。

grant_type OAuth 2.0 仕様で定義されているように、このフィールドの値は refresh_token に設定する必要があります。
refresh_token 認証コード交換から返された更新トークン。

DPoP の使用は任意ですが、セキュリティを強化するため、使用することをおすすめします。更新トークンで DPoP を使用するには、アプリケーションはトークン エンドポイントへのリクエストごとに、新しい一意の DPoP 証明 JWT を生成する必要があります。この証明は、最初の認証コード交換で使用されたものと同じ秘密鍵で署名する必要があります。アプリケーションは、証明を HTTP リクエスト ヘッダーとして追加します。

ヘッダー 必須 説明
DPoP 省略可 DPoP 証明は、秘密鍵の所有を証明する JWT です。これはパラメータではなくヘッダーです。指定すると、返されたトークンがこの鍵にバインドされます。リクエストごとに新しい一意の証明を生成する必要があります。また、リクエストに一致する htm(HTTP メソッド)クレームと htu(HTTP URI)クレームを含める必要があります。

次のスニペットは、リクエストの例を示しています。

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
DPoP: DPOP_PROOF_JWT

client_id=your_client_id&
refresh_token=refresh_token&
grant_type=refresh_token

更新トークンで DPoP を使用するには、リクエストに新しい一意の DPoP 証明 JWT を生成する必要があります。鍵ペアの生成と JWT の作成の手順については、DPoP 証明を作成するをご覧ください。

交換が成功すると、新しいアクセス トークンを含む 200 OK レスポンスが返されます。DPoP を使用する場合、token_type は Bearer です。成功レスポンスは、更新トークンの DPoP 証明が承認されたことを確認します。Google は、レスポンスで新しい DPoP-Nonce HTTP ヘッダーを返すこともあります。返された場合、クライアントはこのノンスをキャッシュに保存し、後続のリクエストの DPoP 証明の nonce クレームに含める必要があります。

DPoP ヘッダーがない、無効である、または間違った鍵を使用している場合、交換に失敗します。特定の DPoP エラーコードとノンスの処理の詳細については、交換の失敗をご覧ください。

次のスニペットは、DPoP が使用されている場合の成功したレスポンス ヘッダーと本文の例を示しています。

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
DPoP-Nonce: AN3XwJjZsjnb0ZuWkRlek8QU7wY-Zhf-5IP6tO0tORz0KgtDT1Bo8FX-w4nz3r5lnepI

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "scope": "https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/calendar.readonly",
  "token_type": "Bearer"
}

発行される更新トークンの数には上限があります。クライアントとユーザーの組み合わせごとに 1 つの上限があり、すべてのクライアントにわたってユーザーごとに別の上限があります。更新トークンは長期ストレージに保存し、有効期限が切れるまで使用し続ける必要があります。アプリケーションがリクエストする更新トークンが多すぎると、この上限に達する可能性があります。その場合、古い更新トークンは機能しなくなります。

トークン失効

ユーザーがアプリケーションに付与したアクセス権を取り消したい場合があります。ユーザーは、 アカウント設定にアクセスしてアクセス権を取り消すことができます。詳しくは、アカウントにアクセスできるサードパーティのアプリやサービスを管理するの「サイトやアプリのアクセス権を削除する」セクションをご覧ください。

アプリケーションは、プログラムによって、付与されたアクセス権を取り消すこともできます。 プログラムによる取り消しは、ユーザーが登録を解除した場合、アプリケーションを削除した場合、アプリに必要な API リソースが大幅に変更された場合などに重要です。つまり、削除プロセスの一部として、アプリに以前付与された権限が削除されるように API リクエストを送信できます。

プログラムでトークンを取り消すには、アプリケーションから https://oauth2.googleapis.com/revoke にリクエストを送信し、パラメータとしてトークンを含めます。

curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
        https://oauth2.googleapis.com/revoke?token={token}

トークンは、アクセス トークンまたは更新トークンです。トークンがアクセス トークンであり、対応する更新トークンがある場合、更新トークンも取り消されます。

取り消しが正常に処理されると、レスポンスの HTTP ステータス コードは 200 になります。エラー状態の場合、HTTP ステータス コード 400 がエラーコードとともに返されます。

アプリのリダイレクト方法

カスタム URI スキーム

カスタム URI スキームは、カスタム定義のスキームを使用してアプリを開くディープリンクの一種です。

Chrome アプリでカスタム URI スキームを使用する代わりの方法

Chrome Identity API を使用します。この API は OAuth 2.0 レスポンスをアプリに直接配信するため、リダイレクト URI は必要ありません。

ループバック IP アドレス(macOS、Linux、Windows デスクトップ)

この URL を使用して認証コードを受け取るには、アプリケーションがローカル ウェブサーバーでリッスンしている必要があります。これは多くのプラットフォームで可能ですが、すべてではありません。ただし、プラットフォームでサポートされている場合は、このメカニズムを使用して認証コードを取得することをおすすめします。

アプリが認可レスポンスを受け取ったとき、ユーザビリティを最大限に高めるには、ブラウザを閉じてアプリに戻るようユーザーに指示する HTML ページを表示して応答する必要があります。

推奨される使い方 macOS、Linux、Windows のデスクトップ アプリ
フォームの値 アプリケーション タイプを [デスクトップ アプリ] に設定します。

手動コピー/貼り付け(非推奨)

アプリを保護する

Chrome のアプリの所有権を確認する

アプリの所有権を確認することで、アプリのなりすましのリスクを軽減できます。

確認プロセスを完了するには、Chrome ウェブストア デベロッパー アカウントを使用します。 確認を完了するには、次の要件を満たす必要があります。

  • 確認を完了する Chrome 拡張機能 OAuth クライアントと同じ商品アイテム ID を持つアイテムが、Chrome ウェブストア デベロッパー ダッシュボードに登録されている必要があります。
  • Chrome ウェブストア アイテムのパブリッシャーである必要があります。 Chrome ウェブストア デベロッパー ダッシュボードでのアクセス管理について詳しくは、こちらをご覧ください。

Chrome 拡張機能クライアントの [アプリの所有権を確認する] セクションで、[所有権を確認する] ボタンをクリックして確認プロセスを完了します。

注: アカウントへのアクセス権を付与してから、確認プロセスを完了するまで数分待ちます。

確認が成功すると、確認プロセスが成功したことを示す通知が表示されます。それ以外の場合は、エラー プロンプトが表示されます。

確認に失敗した場合は、次の手順をお試しください。

  • 確認を完了しようとしている Chrome 拡張機能の OAuth クライアントと同じ商品アイテム ID を持つアイテムが、Chrome ウェブストア デベロッパー ダッシュボードに登録されていることを確認してください。
  • アプリのパブリッシャーであることを確認します。つまり、アプリの個々のパブリッシャーであるか、アプリのグループ パブリッシャーのメンバーである必要があります。Chrome ウェブストア デベロッパー ダッシュボードのアクセス管理について詳しくは、こちらをご覧ください。
  • グループ パブリッシャー リストを更新したばかりの場合は、Chrome ウェブストア デベロッパー ダッシュボードでグループ パブリッシャー メンバーシップ リストが同期されていることを確認します。パブリッシャー メンバーシップ リストの同期について詳しくは、こちらをご覧ください。

App Check(iOS のみ)

App Check 機能は、Apple の App Attest サービスを使用して、Google OAuth 2.0 エンドポイントに対して行われたリクエストが正規のアプリケーションから発信されていることを確認することで、iOS アプリケーションを不正使用から保護します。これにより、アプリのなりすましのリスクを軽減できます。

iOS クライアントで App Check を有効にする

iOS クライアントで App Check を有効にするには、次の要件を満たす必要があります。
  • iOS クライアントのチーム ID を指定する必要があります。
  • バンドル ID にワイルドカードを使用しないでください。複数のアプリに解決される可能性があるためです。つまり、バンドル ID にアスタリスク(*)記号を含めないでください。
App Check を有効にするには、iOS クライアントの編集ビューで [Firebase App Check を使用して、OAuth クライアントを不正行為から保護します] 切り替えボタンをオンにします。

App Check を有効にすると、OAuth クライアントの編集ビューに、クライアントからの OAuth リクエストに関連する指標が表示されるようになります。App Check を適用するまで、未確認のソースからのリクエストはブロックされません。指標モニタリング ページの情報は、適用を開始するタイミングを判断するのに役立ちます。

iOS アプリで App Check を有効にすると、App Check 機能に関連するエラーが表示されることがあります。これらのエラーを修正するには、次の操作を試してください。

  • 指定したバンドル ID とチーム ID が有効であることを確認します。
  • バンドル ID にワイルドカードを使用していないことを確認します。

iOS クライアントに App Check を適用する

アプリで App Check を有効にしても、認識されないリクエストが自動的にブロックされることはありません。この保護を適用するには、iOS クライアントの編集ビューに移動します。ページの右側の [Google Identity for iOS] セクションに App Check の指標が表示されます。指標には次の情報が含まれます。
  • 確認済みリクエストの数 - 有効な App Check トークンを含むリクエスト。App Check の適用を有効にすると、このカテゴリのリクエストのみが成功します。
  • 未確認のリクエスト数: 古いクライアント リクエストの可能性 - App Check トークンがないリクエスト。これらのリクエストは、App Check の実装が含まれていない古いバージョンのアプリからのものである可能性があります。
  • 未検証のリクエスト数: 送信元が不明なリクエスト - App Check トークンがないリクエストで、アプリから送信されていない可能性があります。
  • 未検証のリクエスト数: 無効なリクエスト - 無効な App Check トークン付きのリクエスト。お客様のアプリになりすまそうと試みている偽のクライアント、またはエミュレートされた環境からのものである可能性があります。
これらの指標を確認して、App Check の適用がユーザーに与える影響を把握します。

App Check を適用するには、[ENFORCE] ボタンをクリックして選択内容を確定します。適用が有効になると、クライアントからの未検証のリクエストはすべて拒否されます。

注: 違反措置を有効にした後、変更が反映されるまでに最大で 15 分ほどかかることがあります。

iOS クライアントの App Check の適用を解除する

アプリで App Check の適用を解除すると、適用が停止し、クライアントから Google OAuth 2.0 エンドポイントへのすべてのリクエスト(未検証のリクエストを含む)が許可されます。

iOS クライアントで App Check を適用しないようにするには、iOS クライアントの編集ビューに移動し、[UNENFORCE] ボタンをクリックして選択を確定します。

注: App Check の適用を解除した後、変更が反映されるまでに最大 15 分かかることがあります。

iOS クライアントで App Check を無効にする

アプリで App Check を無効にすると、App Check のすべてのモニタリングと適用が停止します。代わりに、App Check を適用しないことを検討してください。これにより、クライアントの指標のモニタリングを継続できます。

iOS クライアントで App Check を無効にするには、iOS クライアントの編集ビューに移動し、[Firebase App Check を使用して、OAuth クライアントを不正行為から保護します] 切り替えボタンをオフにします。

注: App Check を無効にした後、変更が反映されるまでに最長で 15 分ほどかかることがあります。

時間ベースのアクセス

時間ベースのアクセスでは、ユーザーはアプリにデータへのアクセスを期間限定で許可して、アクションを完了できます。時間ベースのアクセスは、同意フロー中に一部の Google サービスで利用できます。これにより、ユーザーは一定期間アクセスを許可するオプションを選択できます。たとえば、 Data Portability API を使用すると、データを 1 回限り転送できます。

ユーザーがアプリケーションに時間ベースのアクセスを許可すると、指定された期間が経過した後に更新トークンが期限切れになります。更新トークンは、特定の状況下ではより早く無効になる場合があります。詳しくは、こちらのケースをご覧ください。このような場合、認可コード交換レスポンスで返される refresh_token_expires_in フィールドは、更新トークンの有効期限が切れるまでの残り時間を表します。

関連情報

IETF の現在のベスト プラクティスである OAuth 2.0 for ネイティブ アプリ には、ここで説明するベスト プラクティスの多くが記載されています。

クロスアカウント保護機能を実装する

ユーザーのアカウントを保護するための追加の手順として、Google のクロスアカウント保護サービスを利用してクロスアカウント保護機能を実装することをおすすめします。このサービスを使用すると、セキュリティ イベント通知に登録できます。この通知は、ユーザー アカウントの重要な変更に関する情報をアプリケーションに提供します。この情報を使用して、イベントへの対応方法に応じてアクションを実行できます。

Google のクロスアカウント保護機能によってアプリに送信されるイベントタイプの例を以下に示します。

  • https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
  • https://schemas.openid.net/secevent/oauth/event-type/token-revoked
  • https://schemas.openid.net/secevent/risc/event-type/account-disabled

クロスアカウント保護機能の実装方法と、利用可能なイベントの一覧については、 クロスアカウント保護機能でユーザー アカウントを保護する をご覧ください。