ウェブサーバー アプリケーションに OAuth 2.0 を使用する

このドキュメントでは、ウェブサーバー アプリケーションが Google API クライアント ライブラリまたは Google OAuth 2.0 エンドポイントを使用して、Google API への OAuth 2.0 認証を実装する方法について説明します。

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

この OAuth 2.0 フローは、ユーザー認証のみを対象としています。機密情報の保存と状態の維持が可能なアプリケーション向けに設計されています。適切に承認されたウェブサーバー アプリケーションは、ユーザーがアプリケーションを操作している間、またはユーザーがアプリケーションを離れた後に、API にアクセスできます。

ウェブサーバー アプリケーションは、特に Cloud API を呼び出してユーザー固有のデータではなくプロジェクトベースのデータにアクセスする場合に、サービス アカウントを使用して API リクエストを認可します。ウェブサーバー アプリケーションは、ユーザー承認と連携してサービス アカウントを使用できます。

クライアント ライブラリ

このページの言語固有のサンプルでは、Google API クライアント ライブラリを使用して OAuth 2.0 認証を実装しています。サンプルコードを実行するには、ご利用の言語のクライアント ライブラリをインストールしてください。

Google API クライアント ライブラリを使用してアプリケーションの OAuth 2.0 フローを処理する場合、クライアント ライブラリは、アプリケーションが単独で処理する必要のある多くのアクションを実行します。たとえば、アプリケーションが保存済みアクセス トークンを使用または更新できるタイミングや、アプリが同意を再取得する必要があるタイミングを決定します。また、クライアント ライブラリが正しいリダイレクト URL を生成し、アクセス トークン用の認証コードを交換するリダイレクト ハンドラの実装にも役立ちます。

サーバー側アプリケーション用の Google API クライアント ライブラリは、次の言語で利用できます。

Prerequisites

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

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

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

  1. Open the API Library は Google API Consoleにあります。
  2. If prompted, select a project, or create a new one.
  3. API Library 使用可能な API のリストが、プロダクト ファミリーと人気度に応じて分類されます。有効にしたい API がリストで見当たらない場合は、検索してその API を見つけるか、所属するプロダクト ファミリーの [すべて表示] をクリックします。
  4. 有効にする API を選択し、[有効にする] ボタンをクリックします。
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

承認認証情報を作成する

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

  1. Go to the Credentials page.
  2. [認証情報を作成] > [OAuth クライアント ID] をクリックします。
  3. [ウェブ アプリケーション] アプリケーション タイプを選択します。
  4. フォームに記入し、[Create] をクリックします。PHP、Java、Python、Ruby、.NET などの言語やフレームワークを使用するアプリケーションでは、承認済みのリダイレクト URI を指定する必要があります。リダイレクト URI は、OAuth 2.0 サーバーがレスポンスを送信できるエンドポイントです。これらのエンドポイントは、Google の検証ルールを遵守している必要があります。

    テストでは、ローカルマシンを参照する URI(http://localhost:8080 など)を指定できます。このドキュメントで説明する例では、http://localhost:8080 をリダイレクト URI として使用しています。

    アプリの認証エンドポイントを設計して、アプリケーションがページ上の他のリソースに認証コードを公開しないようにすることをおすすめします。

認証情報を作成したら、 API Consoleから client_secret.json ファイルをダウンロードします。アプリケーションのみがアクセスできる場所にファイルを安全に保存します。

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

スコープを使用すると、アプリケーションは必要なリソースへのアクセスのみをリクエストでき、ユーザーはアプリケーションに付与するアクセス権をコントロールできます。したがって、リクエストされたスコープの数とユーザーの同意を取得する可能性の間には、逆関係が存在する場合があります。

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

アプリケーションは、状況に応じてユーザーデータへのアクセスをリクエストする増分認証プロセスを使用して、認証スコープへのアクセスをリクエストすることをおすすめします。このベスト プラクティスは、アプリケーションがアクセスを必要とする理由をユーザーが簡単に理解できるようにします。

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

言語固有の要件

このドキュメントのコードサンプルを実行するには、Google アカウント、インターネットへのアクセス、ウェブブラウザが必要です。API クライアント ライブラリのいずれかを使用している場合は、以下の言語固有の要件もご覧ください。

PHP

このドキュメントの PHP コードサンプルを実行するには、次のものが必要です。

  • PHP 5.4 以降(コマンドライン インターフェース(CLI)と JSON 拡張機能がインストールされている)
  • Composer 依存関係管理ツール。
  • PHP 用 Google API クライアント ライブラリ:

    php composer.phar require google/apiclient:^2.0

Python

このドキュメントの Python コードサンプルを実行するには、次のものが必要です。

  • Python 2.6 以降
  • pip パッケージ管理ツール。
  • Python 用 Google API クライアント ライブラリ:
    pip install --upgrade google-api-python-client
  • ユーザー認可用の google-authgoogle-auth-oauthlibgoogle-auth-httplib2
    pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
  • Flask Python ウェブ アプリケーション フレームワーク。
    pip install --upgrade flask
  • requests HTTP ライブラリ
    pip install --upgrade requests

Ruby

このドキュメントの Ruby コードサンプルを実行するには、次のものが必要です。

  • Ruby 2.2.2 以上
  • Ruby 用 Google API クライアント ライブラリ:

    gem install google-api-client
  • Sinatra Ruby ウェブ アプリケーション フレームワーク。

    gem install sinatra

Node.js

このドキュメントで Node.js コードサンプルを実行するには、次のものが必要です。

  • メンテナンスの LTS、アクティブな LTS、または Node.js の現在のリリース。
  • Google API Node.js クライアント:

    npm install googleapis

HTTP/REST

OAuth 2.0 エンドポイントを直接呼び出すことができるように、ライブラリをインストールする必要はありません。

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

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

手順の概要は次のとおりです。

  1. アプリケーションが必要とする権限を特定します。
  2. アプリケーションは、リクエストされた権限のリストとともに Google にリダイレクトされます。
  3. ユーザーは、アプリケーションに権限を付与するかどうかを決定します。
  4. アプリケーションはユーザーが決定したものを認識します。
  5. ユーザーがリクエストされた権限を付与した場合、アプリケーションはユーザーに代わって API リクエストを行うために必要なトークンを取得します。

ステップ 1: 認証パラメータを設定する

最初のステップとして、承認リクエストを作成します。このリクエストは、アプリを識別するパラメータを設定し、ユーザーにアプリに付与する権限を定義します。

  • OAuth 2.0 認証と認可に Google クライアント ライブラリを使用する場合は、これらのパラメータを定義するオブジェクトを作成し、構成します。
  • Google OAuth 2.0 エンドポイントを直接呼び出す場合は、URL を生成し、その URL にパラメータを設定します。

以下のタブでは、ウェブサーバー アプリケーションでサポートされる認証パラメータを定義しています。言語に固有の例では、クライアント ライブラリまたは認証ライブラリを使用して、これらのパラメータを設定するオブジェクトを構成する方法も示しています。

PHP

次のコード スニペットは、承認リクエストのパラメータを定義する Google_Client() オブジェクトを作成します。

このオブジェクトは、client_secret.json ファイルからの情報を使用してアプリケーションを識別します。(詳しくは、認証情報の作成をご覧ください)。このオブジェクトは、アプリケーションがアクセスをリクエストしているスコープと、アプリケーションの認証エンドポイントの URL も識別します。この認証エンドポイントは、Google の OAuth 2.0 サーバーからのレスポンスを処理します。最後に、このコードではオプションの access_type パラメータと include_granted_scopes パラメータを設定します。

たとえば、次のコードは、ユーザーの Google ドライブへの読み取り専用のオフライン アクセスをリクエストします。

$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
// offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType('offline');
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt("consent");
$client->setIncludeGrantedScopes(true);   // incremental auth

リクエストでは次の情報を指定します。

パラメータ
client_id 必須

アプリケーションのクライアント ID。この値は、 API ConsoleCredentials pageにあります。

PHP で、setAuthConfig 関数を呼び出して、client_secret.json ファイルから認証情報を読み込みます。

$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
redirect_uri 必須

ユーザーが承認フローを完了した後、API サーバーがユーザーをリダイレクトする場所を決定します。この値は、クライアントで構成した OAuth 2.0 クライアントの承認済みリダイレクト URI の API Console Credentials pageと正確に一致している必要があります。この値が、指定された client_id の承認済みのリダイレクト URI と一致しない場合は、redirect_uri_mismatch エラーが発生します。

http または https スキーム、大文字と小文字、末尾のスラッシュ('/')はすべて一致する必要があります。

PHP でこの値を設定するには、setRedirectUri 関数を呼び出します。提供された client_id に有効なリダイレクト URI を指定する必要があります。

$client->setRedirectUri('https://oauth2.example.com/code');
scope 必須

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

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

PHP でこの値を設定するには、addScope 関数を呼び出します。

$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);

可能な限り、アプリケーションにおいてコンテキスト内で承認スコープへのアクセスをリクエストすることをおすすめします。増分承認により、コンテキスト内でユーザーデータへのアクセスをリクエストすることで、アプリケーションがアクセスを必要とする理由をユーザーが簡単に理解できるようになります。

access_type 推奨

ユーザーがブラウザにいないときに、アプリケーションがアクセス トークンを更新できるかどうかを示します。有効なパラメータ値は、デフォルト値の onlineoffline です。

ユーザーがブラウザにいないときにアプリケーションでアクセス トークンを更新する必要がある場合は、値を offline に設定します。これは、このドキュメントの後半で説明するアクセス トークンを更新する方法です。この値は、アプリケーションが初めて認証コードをトークンと交換するときに、更新トークンとアクセス トークンを返すように Google 認証サーバーに指示します。

PHP でこの値を設定するには、setAccessType 関数を呼び出します。

$client->setAccessType('offline');
state 推奨

認証リクエストと認証サーバーのレスポンスとの間の状態を維持するために、アプリケーションが使用する任意の文字列値を指定します。 ユーザーがアプリケーションのアクセス リクエストを同意または拒否した後、redirect_uri の URL クエリ コンポーネント(?)で name=value ペアとして送信した正確な値がサーバーから返されます。

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

PHP でこの値を設定するには、setState 関数を呼び出します。

$client->setState($sample_passthrough_value);
include_granted_scopes 省略可

アプリケーションが増分認可を使用して、状況に応じて追加のスコープへのアクセスをリクエストできるようにします。このパラメータの値を true に設定し、承認リクエストが付与されている場合、ユーザーが以前にアプリケーションへのアクセスを許可したスコープも新しいアクセス トークンによってカバーされます。例については、増分承認をご覧ください。

PHP でこの値を設定するには、setIncludeGrantedScopes 関数を呼び出します。

$client->setIncludeGrantedScopes(true);
login_hint 省略可

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

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

PHP でこの値を設定するには、setLoginHint 関数を呼び出します。

$client->setLoginHint('None');
prompt 省略可

スペースで区切られた、ユーザーに提示するプロンプトのリスト(大文字と小文字を区別)。このパラメータを指定しないと、プロジェクトが最初にアクセスをリクエストしたときにのみメッセージが表示されます。詳細については、再同意のプロンプトをご覧ください。

PHP でこの値を設定するには、setApprovalPrompt 関数を呼び出します。

$client->setApprovalPrompt('consent');

有効な値は次のとおりです。

none 認証画面や同意画面を表示しません。他の値と一緒に指定することはできません。
consent ユーザーに同意を求める。
select_account アカウントの選択をユーザーに求めます。

Python

次のコード スニペットでは、google-auth-oauthlib.flow モジュールを使用して認証リクエストを作成します。

このコードにより Flow オブジェクトが作成されます。このオブジェクトは、認証情報の作成後にダウンロードした client_secret.json ファイルの情報を使用してアプリケーションを識別します。このオブジェクトは、アプリケーションがアクセス権限をリクエストしているスコープと、アプリケーションの認証エンドポイントの URL も識別します。この認証エンドポイントは Google の OAuth 2.0 サーバーからのレスポンスを処理します。最後に、このコードではオプションの access_type パラメータと include_granted_scopes パラメータを設定します。

たとえば、次のコードは、ユーザーの Google ドライブへの読み取り専用のオフライン アクセスをリクエストします。

import google.oauth2.credentials
import google_auth_oauthlib.flow

# Use the client_secret.json file to identify the application requesting
# authorization. The client ID (from that file) and access scopes are required.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

# Indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required. The value must exactly
# match one of the authorized redirect URIs for the OAuth 2.0 client, which you
# configured in the API Console. If this value doesn't match an authorized URI,
# you will get a 'redirect_uri_mismatch' error.
flow.redirect_uri = 'https://www.example.com/oauth2callback'

# Generate URL for request to Google's OAuth 2.0 server.
# Use kwargs to set optional request parameters.
authorization_url, state = flow.authorization_url(
    # Enable offline access so that you can refresh an access token without
    # re-prompting the user for permission. Recommended for web server apps.
    access_type='offline',
    # Enable incremental authorization. Recommended as a best practice.
    include_granted_scopes='true')

リクエストでは次の情報を指定します。

パラメータ
client_id 必須

アプリケーションのクライアント ID。この値は、 API ConsoleCredentials pageにあります。

Python で from_client_secrets_file メソッドを呼び出して、client_secret.json ファイルからクライアント ID を取得します。(from_client_config メソッドを使用することもできます。このメソッドは、クライアント シークレット ファイルに当初表示されていたとおりにクライアント構成を渡しますが、ファイル自体にはアクセスしません)。

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])
redirect_uri 必須

ユーザーが承認フローを完了した後、API サーバーがユーザーをリダイレクトする場所を決定します。この値は、クライアントで構成した OAuth 2.0 クライアントの承認済みリダイレクト URI の API Console Credentials pageと正確に一致している必要があります。この値が、指定された client_id の承認済みのリダイレクト URI と一致しない場合は、redirect_uri_mismatch エラーが発生します。

http または https スキーム、大文字と小文字、末尾のスラッシュ('/')はすべて一致する必要があります。

Python でこの値を設定するには、flow オブジェクトの redirect_uri プロパティを設定します。

flow.redirect_uri = 'https://oauth2.example.com/code'
scope 必須

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

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

Python では、client_id の設定と同じ方法でスコープのリストを指定します。

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

可能な限り、アプリケーションにおいてコンテキスト内で承認スコープへのアクセスをリクエストすることをおすすめします。増分承認により、コンテキスト内でユーザーデータへのアクセスをリクエストすることで、アプリケーションがアクセスを必要とする理由をユーザーが簡単に理解できるようになります。

access_type 推奨

ユーザーがブラウザにいないときに、アプリケーションがアクセス トークンを更新できるかどうかを示します。有効なパラメータ値は、デフォルト値の onlineoffline です。

ユーザーがブラウザにいないときにアプリケーションでアクセス トークンを更新する必要がある場合は、値を offline に設定します。これは、このドキュメントの後半で説明するアクセス トークンを更新する方法です。この値は、アプリケーションが初めて認証コードをトークンと交換するときに、更新トークンとアクセス トークンを返すように Google 認証サーバーに指示します。

Python で access_type パラメータを設定するには、flow.authorization_url メソッドを呼び出すときにキーワード引数として access_type を指定します。

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
state 推奨

認証リクエストと認証サーバーのレスポンスとの間の状態を維持するために、アプリケーションが使用する任意の文字列値を指定します。 ユーザーがアプリケーションのアクセス リクエストを同意または拒否した後、redirect_uri の URL クエリ コンポーネント(?)で name=value ペアとして送信した正確な値がサーバーから返されます。

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

Python で state パラメータを設定するには、flow.authorization_url メソッドを呼び出すときにキーワード引数として state を指定します。

authorization_url, state = flow.authorization_url(
    access_type='offline',
    state=sample_passthrough_value,
    include_granted_scopes='true')
include_granted_scopes 省略可

アプリケーションが増分認可を使用して、状況に応じて追加のスコープへのアクセスをリクエストできるようにします。このパラメータの値を true に設定し、承認リクエストが付与されている場合、ユーザーが以前にアプリケーションへのアクセスを許可したスコープも新しいアクセス トークンによってカバーされます。例については、増分承認をご覧ください。

Python で include_granted_scopes パラメータを設定するには、flow.authorization_url メソッドを呼び出すときにキーワード引数として include_granted_scopes を指定します。

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
login_hint 省略可

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

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

Python で login_hint パラメータを設定するには、flow.authorization_url メソッドを呼び出すときにキーワード引数として login_hint を指定します。

authorization_url, state = flow.authorization_url(
    access_type='offline',
    login_hint='None',
    include_granted_scopes='true')
prompt 省略可

スペースで区切られた、ユーザーに提示するプロンプトのリスト(大文字と小文字を区別)。このパラメータを指定しないと、プロジェクトが最初にアクセスをリクエストしたときにのみメッセージが表示されます。詳細については、再同意のプロンプトをご覧ください。

Python で prompt パラメータを設定するには、flow.authorization_url メソッドを呼び出すときにキーワード引数として prompt を指定します。

authorization_url, state = flow.authorization_url(
      access_type='offline',
      prompt='consent',
      include_granted_scopes='true')

有効な値は次のとおりです。

none 認証画面や同意画面を表示しません。他の値と一緒に指定することはできません。
consent ユーザーに同意を求める。
select_account アカウントの選択をユーザーに求めます。

Ruby

作成した client_secrets.json ファイルを使用して、アプリケーションでクライアント オブジェクトを構成します。クライアント オブジェクトを構成するときは、アプリケーションがアクセスするスコープを、OAuth 2.0 サーバーからのレスポンスを処理するアプリケーションの認証エンドポイントの URL を指定します。

たとえば、次のコードは、ユーザーの Google ドライブへの読み取り専用のオフライン アクセスをリクエストします。

require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'

client_secrets = Google::APIClient::ClientSecrets.load
auth_client = client_secrets.to_authorization
auth_client.update!(
  :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
  :redirect_uri => 'http://www.example.com/oauth2callback',
  :additional_parameters => {
    "access_type" => "offline",         # offline access
    "include_granted_scopes" => "true"  # incremental auth
  }
)

アプリケーションは、このクライアント オブジェクトを使用して、認証リクエスト URL の生成や HTTP リクエストへのアクセス トークンの適用など、OAuth 2.0 オペレーションを実行します。

Node.js

次のコード スニペットは、承認リクエストのパラメータを定義する google.auth.OAuth2 オブジェクトを作成します。

このオブジェクトは、client_secret.json ファイルからの情報を使用してアプリケーションを識別します。アクセス トークンの取得についてユーザーに権限をリクエストするには、ユーザーを同意ページにリダイレクトします。同意ページの URL を作成するには:

const {google} = require('googleapis');

/**
 * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI
 * from the client_secret.json file. To get these credentials for your application, visit
 * https://console.cloud.google.com/apis/credentials.
 */
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for read-only Drive activity.
const scopes = [
  'https://www.googleapis.com/auth/drive.metadata.readonly'
];

// Generate a url that asks permissions for the Drive activity scope
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  /** Pass in the scopes array defined above.
    * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
  scope: scopes,
  // Enable incremental authorization. Recommended as a best practice.
  include_granted_scopes: true
});

重要な注意事項 - refresh_token は、最初の承認時にのみ返されます。詳しくは、こちらをご覧ください。

HTTP/REST

Google の OAuth 2.0 エンドポイントは https://accounts.google.com/o/oauth2/v2/auth にあります。このエンドポイントには HTTPS 経由でのみアクセスできます。プレーン HTTP 接続は拒否されます。

Google 承認サーバーは、ウェブサーバー アプリケーションで次のクエリ文字列パラメータをサポートしています。

パラメータ
client_id 必須

アプリケーションのクライアント ID。この値は、 API ConsoleCredentials pageにあります。

redirect_uri 必須

ユーザーが承認フローを完了した後、API サーバーがユーザーをリダイレクトする場所を決定します。この値は、クライアントで構成した OAuth 2.0 クライアントの承認済みリダイレクト URI の API Console Credentials pageと正確に一致している必要があります。この値が、指定された client_id の承認済みのリダイレクト URI と一致しない場合は、redirect_uri_mismatch エラーが発生します。

http または https スキーム、大文字と小文字、末尾のスラッシュ('/')はすべて一致する必要があります。

response_type 必須

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

ウェブサーバー アプリケーションのパラメータ値を code に設定します。

scope 必須

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

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

可能な限り、アプリケーションにおいてコンテキスト内で承認スコープへのアクセスをリクエストすることをおすすめします。増分承認により、コンテキスト内でユーザーデータへのアクセスをリクエストすることで、アプリケーションがアクセスを必要とする理由をユーザーが簡単に理解できるようになります。

access_type 推奨

ユーザーがブラウザにいないときに、アプリケーションがアクセス トークンを更新できるかどうかを示します。有効なパラメータ値は、デフォルト値の onlineoffline です。

ユーザーがブラウザにいないときにアプリケーションでアクセス トークンを更新する必要がある場合は、値を offline に設定します。これは、このドキュメントの後半で説明するアクセス トークンを更新する方法です。この値は、アプリケーションが初めて認証コードをトークンと交換するときに、更新トークンとアクセス トークンを返すように Google 認証サーバーに指示します。

state 推奨

認証リクエストと認証サーバーのレスポンスとの間の状態を維持するために、アプリケーションが使用する任意の文字列値を指定します。 ユーザーがアプリケーションのアクセス リクエストを同意または拒否した後、redirect_uri の URL クエリ コンポーネント(?)で name=value ペアとして送信した正確な値がサーバーから返されます。

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

include_granted_scopes 省略可

アプリケーションが増分認可を使用して、状況に応じて追加のスコープへのアクセスをリクエストできるようにします。このパラメータの値を true に設定し、承認リクエストが付与されている場合、ユーザーが以前にアプリケーションへのアクセスを許可したスコープも新しいアクセス トークンによってカバーされます。例については、増分承認をご覧ください。

login_hint 省略可

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

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

prompt 省略可

スペースで区切られた、ユーザーに提示するプロンプトのリスト(大文字と小文字を区別)。このパラメータを指定しないと、プロジェクトが最初にアクセスをリクエストしたときにのみメッセージが表示されます。詳細については、再同意のプロンプトをご覧ください。

有効な値は次のとおりです。

none 認証画面や同意画面を表示しません。他の値と一緒に指定することはできません。
consent ユーザーに同意を求める。
select_account アカウントの選択をユーザーに求めます。

ステップ 2: Google の OAuth 2.0 サーバーにリダイレクトする

ユーザーを Google の OAuth 2.0 サーバーにリダイレクトして、認証と認可のプロセスを開始します。通常、これはアプリケーションが最初にユーザーのデータにアクセスする必要がある場合に発生します。段階的な認証の場合、このステップは、アプリケーションがまだアクセス権を持たない追加のリソースにアクセスする必要がある場合にも発生します。

PHP

  1. Google の OAuth 2.0 サーバーからのアクセスをリクエストする URL を生成します。
    $auth_url = $client->createAuthUrl();
  2. ユーザーを $auth_url にリダイレクトします。
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Python

次の例は、Flask ウェブ アプリケーション フレームワークを使用して、ユーザーを認可 URL にリダイレクトする方法を示しています。

return flask.redirect(authorization_url)

Ruby

  1. Google の OAuth 2.0 サーバーからのアクセスをリクエストする URL を生成します:
    auth_uri = auth_client.authorization_uri.to_s
  2. ユーザーを auth_uri にリダイレクトします。

Node.js

  1. ステップ 1generateAuthUrl メソッドで生成された URL authorizationUrl を使用して、Google の OAuth 2.0 サーバーからのアクセスをリクエストします。
  2. ユーザーを authorizationUrl にリダイレクトします。
    res.writeHead(301, { "Location": authorizationUrl });

HTTP/REST

Sample redirect to Google's authorization server

An example URL is shown below, with line breaks and spaces for readability.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

リクエスト URL を作成したら、ユーザーをその URL にリダイレクトします。

Google の OAuth 2.0 サーバーは、ユーザーを認証し、アプリケーションがリクエストされたスコープにアクセスするための同意を取得します。指定したリダイレクト URL を使用して、アプリケーションにレスポンスが返されます。

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

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

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

エラー

Google の OAuth 2.0 認証エンドポイントへのリクエストでは、予想される認証および認可フローの代わりにユーザー向けのエラー メッセージが表示されることがあります。一般的なエラーコードとおすすめの解決方法を以下に示します。

admin_policy_enforced

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

disallowed_useragent

認証エンドポイントは、Google の OAuth 2.0 ポリシーで禁止されているユーザー エージェント内に表示されます。

Android

Android デベロッパーが android.webkit.WebView で認証リクエストを開くと、このエラー メッセージが表示されることがあります。代わりに、Android 用 Google ログインや OpenID Foundation の Android 用 AppAuth などの Android ライブラリを使用する必要があります。

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

iOS

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

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

org_internal

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

redirect_uri_mismatch

認可リクエストで渡された redirect_uri が、OAuth クライアント ID の承認されたリダイレクト URI と一致しません。 Google API Console Credentials pageで承認済みのリダイレクト URI を確認してください。

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

OAuth 2.0 サーバーは、リクエストで指定された URL を使用してアプリケーションのアクセス リクエストに応答します。

ユーザーがアクセス リクエストを承認すると、レスポンスに認証コードが含まれます。ユーザーがリクエストを承認しない場合、レスポンスにエラー メッセージが含まれます。次のように、ウェブサーバーに返される認証コードまたはエラー メッセージがクエリ文字列に表示されます。

エラー レスポンス:

https://oauth2.example.com/auth?error=access_denied

認証コードのレスポンス:

https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7

OAuth 2.0 サーバー レスポンスの例

このフローをテストするには、次のサンプル URL をクリックして、Google ドライブ内のファイルのメタデータを表示するための読み取り専用アクセスをリクエストします。

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

OAuth 2.0 フローが完了すると、http://localhost/oauth2callback にリダイレクトされます。これにより、ローカルマシンがそのアドレスでファイルを提供しない限り、404 NOT FOUND エラーが発生する可能性があります。次のステップでは、ユーザーがアプリケーションにリダイレクトされたときに URI で返される情報について詳しく説明します。

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

ウェブサーバーは、認証コードを受信すると、認証コードをアクセス トークンと交換できます。

PHP

認証コードをアクセス トークンと交換するには、authenticate メソッドを使用します。

$client->authenticate($_GET['code']);

アクセス トークンは getAccessToken メソッドで取得できます。

$access_token = $client->getAccessToken();

Python

コールバック ページで、google-auth ライブラリを使用して認証サーバーのレスポンスを確認します。次に、flow.fetch_token メソッドを使用して、レスポンス内の認証コードをアクセス トークンと交換します。

state = flask.session['state']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'],
    state=state)
flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

authorization_response = flask.request.url
flow.fetch_token(authorization_response=authorization_response)

# Store the credentials in the session.
# ACTION ITEM for developers:
#     Store user's access and refresh tokens in your data store if
#     incorporating this code into your real app.
credentials = flow.credentials
flask.session['credentials'] = {
    'token': credentials.token,
    'refresh_token': credentials.refresh_token,
    'token_uri': credentials.token_uri,
    'client_id': credentials.client_id,
    'client_secret': credentials.client_secret,
    'scopes': credentials.scopes}

Ruby

認証コードをアクセス トークンと交換するには、fetch_access_token! メソッドを使用します。

auth_client.code = auth_code
auth_client.fetch_access_token!

Node.js

認証コードをアクセス トークンと交換するには、getToken メソッドを使用します。

const url = require('url');

// Receive the callback from Google's OAuth 2.0 server.
if (req.url.startsWith('/oauth2callback')) {
  // Handle the OAuth 2.0 server response
  let q = url.parse(req.url, true).query;

  // Get access and refresh tokens (if access_type is offline)
  let { tokens } = await oauth2Client.getToken(q.code);
  oauth2Client.setCredentials(tokens);
}

HTTP/REST

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

フィールド
client_id Credentials pageから取得したクライアント ID。 API Console
client_secret Credentials pageから取得したクライアント シークレット。 API Console
code 最初のリクエストから返された認証コード。
grant_type OAuth 2.0 仕様で定義されている場合、このフィールドの値は authorization_code に設定する必要があります。
redirect_uri 指定された client_id の API ConsoleCredentials page 内のプロジェクトのリダイレクト URI の 1 つ。

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

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

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code

Google は、このリクエストに対して、有効期間が短いアクセス トークンと更新トークンを含む JSON オブジェクトを返します。更新トークンが返されるのは、アプリケーションが Google 承認サーバーへの最初のリクエストaccess_type パラメータを offline に設定した場合のみです。

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

フィールド
access_token Google API リクエストを認可するためにアプリケーションが送信するトークン。
expires_in アクセス トークンの有効期間(秒)です。
refresh_token 新しいアクセス トークンの取得に使用できるトークン。更新トークンは、ユーザーがアクセス権を取り消すまで有効です。 ここでも、このフィールドは、Google 承認サーバーへの最初のリクエストで access_type パラメータを offline に設定した場合にのみ、このレスポンスに含まれます。
scope access_token によって付与されるアクセスのスコープ。スペース区切りの大文字と小文字が区別される文字列のリストとして表されます。
token_type 返されるトークンのタイプ。現時点では、このフィールドの値は常に Bearer に設定されます。

次のスニペットは、レスポンスの例を示しています。

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

Google API の呼び出し

PHP

アクセス トークンを使用して Google API を呼び出す手順は次のとおりです。

  1. 新しい Google_Client オブジェクトにアクセス トークンを適用する必要がある場合(ユーザー セッションでアクセス トークンを保存した場合など)は、setAccessToken メソッドを使用します。
    $client->setAccessToken($access_token);
  2. 呼び出す API のサービス オブジェクトをビルドします。サービス オブジェクトを作成するには、呼び出し先の API のコンストラクタに承認済みの Google_Client オブジェクトを指定します。 たとえば、Drive API を呼び出すには次のようにします。
    $drive = new Google_Service_Drive($client);
  3. サービス オブジェクトで提供されるインターフェースを使用して API サービスへのリクエストを行います。たとえば、認証されたユーザーの Google ドライブ内のファイルを一覧表示するには、次のようにします。
    $files = $drive->files->listFiles(array())->getItems();

Python

アクセス トークンを取得した後、アプリケーションは、そのトークンを使用して、特定のユーザーまたはサービス アカウントに代わって API リクエストを認可できます。ユーザー固有の認証情報を使用して、呼び出す API のサービス オブジェクトを作成し、そのオブジェクトを使用して承認済みの API リクエストを作成します。

  1. 呼び出す API のサービス オブジェクトをビルドします。サービス ライブラリを作成するには、googleapiclient.discovery ライブラリの build メソッドを呼び出して、API の名前とユーザーの認証情報を設定します。 たとえば、Drive API のバージョン 2 を呼び出すには、以下を使用します。
    from googleapiclient.discovery import build
    
    drive = build('drive', 'v2', credentials=credentials)
  2. サービス オブジェクトで提供されるインターフェースを使用して API サービスへのリクエストを行います。たとえば、認証されたユーザーの Google ドライブ内のファイルを一覧表示するには、次のようにします。
    files = drive.files().list().execute()

Ruby

auth_client オブジェクトを使用し、次の手順を行って Google API を呼び出します。

  1. 呼び出す API のサービス オブジェクトをビルドします。たとえば、Drive API のバージョン 2 を呼び出すには、次のようにします。
    drive = Google::Apis::DriveV2::DriveService.new
  2. サービスで認証情報を設定します。
    drive.authorization = auth_client
  3. サービス オブジェクトで提供されるインターフェースを使用して API サービスへのリクエストを行います。たとえば、認証されたユーザーの Google ドライブ内のファイルを一覧表示するには、次のようにします。
    files = drive.list_files

または、メソッドに options パラメータを指定することで、メソッドごとに承認を行うことができます。

files = drive.list_files(options: { authorization: auth_client })

Node.js

アクセス トークンを取得して OAuth2 オブジェクトに設定したら、そのオブジェクトを使用して Google API を呼び出します。アプリケーションは、このトークンを使用して、特定のユーザー アカウントまたはサービス アカウントに代わって API リクエストを承認できます。呼び出す API のサービス オブジェクトをビルドします。

const { google } = require('googleapis');

// Example of using Google Drive API to list filenames in user's Drive.
const drive = google.drive('v3');
drive.files.list({
  auth: oauth2Client,
  pageSize: 10,
  fields: 'nextPageToken, files(id, name)',
}, (err1, res1) => {
  if (err1) return console.log('The API returned an error: ' + err1);
  const files = res1.data.files;
  if (files.length) {
    console.log('Files:');
    files.map((file) => {
      console.log(`${file.name} (${file.id})`);
    });
  } else {
    console.log('No files found.');
  }
});

HTTP/REST

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

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

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

完全な例

次の例では、ユーザーが認証された後で、ユーザーの Google ドライブ内のメタデータにアクセスすることを JSON ファイル形式で Google ドライブに出力します。

PHP

この例を実行する手順は次のとおりです。

  1. API Consoleで、リダイレクト URL のリストにローカルマシンの URL を追加します。たとえば、http://localhost:8080 を追加します。
  2. 新しいディレクトリを作成し、そのディレクトリに移動します。例:
    mkdir ~/php-oauth2-example
    cd ~/php-oauth2-example
  3. Composer を使用して PHP の Google API クライアント ライブラリをインストールします。
    composer require google/apiclient:^2.0
  4. 次の内容の index.phpoauth2callback.php を作成します。
  5. PHP を提供するように構成されたウェブサーバーで、例を実行します。PHP 5.4 以降を使用している場合は、PHP の組み込みテスト ウェブサーバー
    php -S localhost:8080 ~/php-oauth2-example
    を使用できます。

index.php

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfig('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);

if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  $drive = new Google_Service_Drive($client);
  $files = $drive->files->listFiles(array())->getItems();
  echo json_encode($files);
} else {
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

oauth2callback.php

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);

if (! isset($_GET['code'])) {
  $auth_url = $client->createAuthUrl();
  header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
  $client->authenticate($_GET['code']);
  $_SESSION['access_token'] = $client->getAccessToken();
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

Python

この例では、Flask フレームワークを使用します。http://localhost:8080 でウェブ アプリケーションを実行し、OAuth 2.0 フローをテストします。その URL に移動すると、4 つのリンクが表示されます。

  • API リクエストのテスト: このリンクは、サンプル API リクエストを実行しようとするページを指します。必要に応じて、承認フローが開始されます。成功すると、ページに API レスポンスが表示されます。
  • 認証フローを直接テストする場合: このリンクは、承認フローを通じてユーザーに情報を送信しようとするページを指し示します。アプリがユーザーに代わって承認済みの API リクエストを送信する権限をリクエストします。
  • 現在の認証情報を取り消す: このリンクは、ユーザーがアプリケーションにすでに付与した権限を取り消すページを指しています。
  • Flask セッションの認証情報を消去: このリンクでは、Flask セッションに保存されている認証情報がクリアされます。これにより、すでにアプリに権限を付与しているユーザーが新しいセッションで API リクエストを実行しようとした場合に何が起こるかを確認できます。また、ユーザーがアプリに付与されている権限を取り消した後、アプリが取り消されたアクセス トークンを含むリクエストを認可しようとした場合にアプリが取得する API レスポンスを確認することもできます。
# -*- coding: utf-8 -*-

import os
import flask
import requests

import google.oauth2.credentials
import google_auth_oauthlib.flow
import googleapiclient.discovery

# This variable specifies the name of a file that contains the OAuth 2.0
# information for this application, including its client_id and client_secret.
CLIENT_SECRETS_FILE = "client_secret.json"

# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account and requires requests to use an SSL connection.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
API_SERVICE_NAME = 'drive'
API_VERSION = 'v2'

app = flask.Flask(__name__)
# Note: A secret key is included in the sample so that it works.
# If you use this code in your application, replace this with a truly secret
# key. See https://flask.palletsprojects.com/quickstart/#sessions.
app.secret_key = 'REPLACE ME - this value is here as a placeholder.'


@app.route('/')
def index():
  return print_index_table()


@app.route('/test')
def test_api_request():
  if 'credentials' not in flask.session:
    return flask.redirect('authorize')

  # Load credentials from the session.
  credentials = google.oauth2.credentials.Credentials(
      **flask.session['credentials'])

  drive = googleapiclient.discovery.build(
      API_SERVICE_NAME, API_VERSION, credentials=credentials)

  files = drive.files().list().execute()

  # Save credentials back to session in case access token was refreshed.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.jsonify(**files)


@app.route('/authorize')
def authorize():
  # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps.
  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES)

  # The URI created here must exactly match one of the authorized redirect URIs
  # for the OAuth 2.0 client, which you configured in the API Console. If this
  # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch'
  # error.
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  authorization_url, state = flow.authorization_url(
      # Enable offline access so that you can refresh an access token without
      # re-prompting the user for permission. Recommended for web server apps.
      access_type='offline',
      # Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes='true')

  # Store the state so the callback can verify the auth server response.
  flask.session['state'] = state

  return flask.redirect(authorization_url)


@app.route('/oauth2callback')
def oauth2callback():
  # Specify the state when creating the flow in the callback so that it can
  # verified in the authorization server response.
  state = flask.session['state']

  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  # Use the authorization server's response to fetch the OAuth 2.0 tokens.
  authorization_response = flask.request.url
  flow.fetch_token(authorization_response=authorization_response)

  # Store credentials in the session.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  credentials = flow.credentials
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.redirect(flask.url_for('test_api_request'))


@app.route('/revoke')
def revoke():
  if 'credentials' not in flask.session:
    return ('You need to <a href="/authorize">authorize</a> before ' +
            'testing the code to revoke credentials.')

  credentials = google.oauth2.credentials.Credentials(
    **flask.session['credentials'])

  revoke = requests.post('https://oauth2.googleapis.com/revoke',
      params={'token': credentials.token},
      headers = {'content-type': 'application/x-www-form-urlencoded'})

  status_code = getattr(revoke, 'status_code')
  if status_code == 200:
    return('Credentials successfully revoked.' + print_index_table())
  else:
    return('An error occurred.' + print_index_table())


@app.route('/clear')
def clear_credentials():
  if 'credentials' in flask.session:
    del flask.session['credentials']
  return ('Credentials have been cleared.<br><br>' +
          print_index_table())


def credentials_to_dict(credentials):
  return {'token': credentials.token,
          'refresh_token': credentials.refresh_token,
          'token_uri': credentials.token_uri,
          'client_id': credentials.client_id,
          'client_secret': credentials.client_secret,
          'scopes': credentials.scopes}

def print_index_table():
  return ('<table>' +
          '<tr><td><a href="/test">Test an API request</a></td>' +
          '<td>Submit an API request and see a formatted JSON response. ' +
          '    Go through the authorization flow if there are no stored ' +
          '    credentials for the user.</td></tr>' +
          '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' +
          '<td>Go directly to the authorization flow. If there are stored ' +
          '    credentials, you still might not be prompted to reauthorize ' +
          '    the application.</td></tr>' +
          '<tr><td><a href="/revoke">Revoke current credentials</a></td>' +
          '<td>Revoke the access token associated with the current user ' +
          '    session. After revoking credentials, if you go to the test ' +
          '    page, you should see an <code>invalid_grant</code> error.' +
          '</td></tr>' +
          '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' +
          '<td>Clear the access token currently stored in the user session. ' +
          '    After clearing the token, if you <a href="/test">test the ' +
          '    API request</a> again, you should go back to the auth flow.' +
          '</td></tr></table>')


if __name__ == '__main__':
  # When running locally, disable OAuthlib's HTTPs verification.
  # ACTION ITEM for developers:
  #     When running in production *do not* leave this option enabled.
  os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

  # Specify a hostname and port that are set as a valid redirect URI
  # for your API project in the Google API Console.
  app.run('localhost', 8080, debug=True)

Ruby

この例では、Sinatra フレームワークを使用します。

require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'
require 'json'
require 'sinatra'

enable :sessions
set :session_secret, 'setme'

get '/' do
  unless session.has_key?(:credentials)
    redirect to('/oauth2callback')
  end
  client_opts = JSON.parse(session[:credentials])
  auth_client = Signet::OAuth2::Client.new(client_opts)
  drive = Google::Apis::DriveV2::DriveService.new
  files = drive.list_files(options: { authorization: auth_client })
  "<pre>#{JSON.pretty_generate(files.to_h)}</pre>"
end

get '/oauth2callback' do
  client_secrets = Google::APIClient::ClientSecrets.load
  auth_client = client_secrets.to_authorization
  auth_client.update!(
    :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
    :redirect_uri => url('/oauth2callback'))
  if request['code'] == nil
    auth_uri = auth_client.authorization_uri.to_s
    redirect to(auth_uri)
  else
    auth_client.code = request['code']
    auth_client.fetch_access_token!
    auth_client.client_secret = nil
    session[:credentials] = auth_client.to_json
    redirect to('/')
  end
end

Node.js

この例を実行する手順は次のとおりです。

  1. API Consoleで、リダイレクト URL のリストにローカルマシンの URL を追加します。たとえば、http://localhost を追加します。
  2. メンテナンスの LTS、アクティブな LTS、Node.js の最新リリースがインストールされていることを確認します。
  3. 新しいディレクトリを作成し、そのディレクトリに移動します。例:
    mkdir ~/nodejs-oauth2-example
    cd ~/nodejs-oauth2-example
  4. Install the Google API Client Library for Node.js using npm:
    npm install googleapis
  5. 以下の内容で main.js ファイルを作成します。
  6. サンプルを実行します。
    node .\main.js

main.js

const http = require('http');
const https = require('https');
const url = require('url');
const { google } = require('googleapis');

/**
 * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI.
 * To get these credentials for your application, visit
 * https://console.cloud.google.com/apis/credentials.
 */
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for read-only Drive activity.
const scopes = [
  'https://www.googleapis.com/auth/drive.metadata.readonly'
];

// Generate a url that asks permissions for the Drive activity scope
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  /** Pass in the scopes array defined above.
    * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
  scope: scopes,
  // Enable incremental authorization. Recommended as a best practice.
  include_granted_scopes: true
});

/* Global variable that stores user credential in this code example.
 * ACTION ITEM for developers:
 *   Store user's refresh token in your data store if
 *   incorporating this code into your real app.
 *   For more information on handling refresh tokens,
 *   see https://github.com/googleapis/google-api-nodejs-client#handling-refresh-tokens
 */
let userCredential = null;

async function main() {
  const server = http.createServer(async function (req, res) {
    // Example on redirecting user to Google's OAuth 2.0 server.
    if (req.url == '/') {
      res.writeHead(301, { "Location": authorizationUrl });
    }

    // Receive the callback from Google's OAuth 2.0 server.
    if (req.url.startsWith('/oauth2callback')) {
      // Handle the OAuth 2.0 server response
      let q = url.parse(req.url, true).query;

      if (q.error) { // An error response e.g. error=access_denied
        console.log('Error:' + q.error);
      } else { // Get access and refresh tokens (if access_type is offline)
        let { tokens } = await oauth2Client.getToken(q.code);
        oauth2Client.setCredentials(tokens);

        /** Save credential to the global variable in case access token was refreshed.
          * ACTION ITEM: In a production app, you likely want to save the refresh token
          *              in a secure persistent database instead. */
        userCredential = tokens;

        // Example of using Google Drive API to list filenames in user's Drive.
        const drive = google.drive('v3');
        drive.files.list({
          auth: oauth2Client,
          pageSize: 10,
          fields: 'nextPageToken, files(id, name)',
        }, (err1, res1) => {
          if (err1) return console.log('The API returned an error: ' + err1);
          const files = res1.data.files;
          if (files.length) {
            console.log('Files:');
            files.map((file) => {
              console.log(`${file.name} (${file.id})`);
            });
          } else {
            console.log('No files found.');
          }
        });
      }
    }

    // Example on revoking a token
    if (req.url == '/revoke') {
      // Build the string for the POST request
      let postData = "token=" + userCredential.access_token;

      // Options for POST request to Google's OAuth 2.0 server to revoke a token
      let postOptions = {
        host: 'oauth2.googleapis.com',
        port: '443',
        path: '/revoke',
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': Buffer.byteLength(postData)
        }
      };

      // Set up the request
      const postReq = https.request(postOptions, function (res) {
        res.setEncoding('utf8');
        res.on('data', d => {
          console.log('Response: ' + d);
        });
      });

      postReq.on('error', error => {
        console.log(error)
      });

      // Post the request with data
      postReq.write(postData);
      postReq.end();
    }
    res.end();
  }).listen(80);
}
main().catch(console.error);

HTTP/REST

この Python の例では、Flask フレームワークと Requests ライブラリを使用して OAuth 2.0 ウェブフローを示します。このフローでは、Python 用 Google API クライアント ライブラリを使用することをおすすめします。(Python タブの例では、クライアント ライブラリを使用しています)。

import json

import flask
import requests


app = flask.Flask(__name__)

CLIENT_ID = '123456789.apps.googleusercontent.com'
CLIENT_SECRET = 'abc123'  # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly'
REDIRECT_URI = 'http://example.com/oauth2callback'


@app.route('/')
def index():
  if 'credentials' not in flask.session:
    return flask.redirect(flask.url_for('oauth2callback'))
  credentials = json.loads(flask.session['credentials'])
  if credentials['expires_in'] <= 0:
    return flask.redirect(flask.url_for('oauth2callback'))
  else:
    headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
    req_uri = 'https://www.googleapis.com/drive/v2/files'
    r = requests.get(req_uri, headers=headers)
    return r.text


@app.route('/oauth2callback')
def oauth2callback():
  if 'code' not in flask.request.args:
    auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code'
                '&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE)
    return flask.redirect(auth_uri)
  else:
    auth_code = flask.request.args.get('code')
    data = {'code': auth_code,
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'redirect_uri': REDIRECT_URI,
            'grant_type': 'authorization_code'}
    r = requests.post('https://oauth2.googleapis.com/token', data=data)
    flask.session['credentials'] = r.text
    return flask.redirect(flask.url_for('index'))


if __name__ == '__main__':
  import uuid
  app.secret_key = str(uuid.uuid4())
  app.debug = False
  app.run()

リダイレクト URI 検証ルール

Google では、アプリケーションがセキュリティを維持できるように、URI のリダイレクトに次の検証ルールを適用します。リダイレクト URI は、上記の規則に従う必要があります。以下で説明するドメイン、ホスト、パス、クエリ、スキーム、ユーザー情報の定義については、RFC 3986 セクション 3 をご覧ください。

検証ルール
スキーム

リダイレクト URI は、プレーン HTTP ではなく HTTPS スキームを使用する必要があります。ローカルホスト URI(localhost IP アドレス URI を含む)は、このルールから除外されます。

ホスト

ホストには、未加工の IP アドレスは使用できません。ローカルホスト IP アドレスはこのルールから除外されます。

ドメイン
  • ホスト TLD(トップレベル ドメイン)は、パブリック サフィックス リストに属している必要があります。
  • ホストドメインを “googleusercontent.com” にすることはできません。
  • アプリがそのドメインを所有している場合を除き、リダイレクト URI に URL 短縮ドメイン(例: goo.gl)を含めることはできません。さらに、短縮ドメインを所有するアプリがそのドメインにリダイレクトすることを選択した場合、そのリダイレクト URI はパスに “/google-callback/” を含むか、“/google-callback” で終わる必要があります。
  • Userinfo

    リダイレクト URI に userinfo サブコンポーネントを含めることはできません。

    [Path]

    リダイレクト URI には、“/..” または “\..”、あるいはそれらの URL エンコードで表されるパス トラバーサル(ディレクトリ バックトラッキングとも呼ばれます)を含めることはできません。

    検索キーワード

    リダイレクト URI にオープン リダイレクトを含めることはできません。

    フラグメント

    リダイレクト URI にフラグメント コンポーネントを含めることはできません。

    文字 リダイレクト URI には、次のような文字は使用できません。
    • ワイルドカード文字('*'
    • 印刷できない ASCII 文字
    • パーセント エンコードが無効です(URL エンコード形式のパーセント記号に 2 桁の 16 進数記号を追加しない任意のパーセント エンコード)
    • Null 文字(エンコードされた NULL 文字、例:%00%C0%80

    増分承認

    OAuth 2.0 プロトコルでは、アプリはスコープによって識別されるリソースにアクセスするための承認をリクエストします。リソースの承認を必要なときにリクエストすることをおすすめします。これを可能にするため、Google の承認サーバーは増分承認に対応しています。この機能を使用すると、必要に応じてスコープをリクエストできます。ユーザーが新しいスコープの権限を付与すると、ユーザーがプロジェクトに付与したすべてのスコープを含むトークンと交換できる認証コードを返します。

    たとえば、ユーザーが音楽トラックをサンプリングしてミックスを作成できるアプリでは、ログイン時に必要となるリソースがほとんどなく、ログインする人の名前だけで十分です。ただし、完成したミックスを保存するには、Google ドライブにアクセスする必要があります。ほとんどのユーザーは、実際にアプリが必要とした時点で Google ドライブへのアクセスを要求するだけで、自然にできませんでした。

    この場合、アプリはログイン時に openid スコープと profile スコープをリクエストして基本的なログインを行い、その後、最初のリクエスト時にミックスリストを保存する https://www.googleapis.com/auth/drive.file スコープをリクエストします。

    段階的認証を実装するには、アクセス トークンをリクエストする通常のフローを完了しますが、認可リクエストに以前に付与したスコープが含まれていることを確認します。このアプローチにより、アプリは複数のアクセス トークンを管理する必要がありません。

    増分承認から取得したアクセス トークンには、以下のルールが適用されます。

    • このトークンを使用して、新しい結合された承認にロールされたスコープに対応するリソースにアクセスできます。
    • アクセス トークンを取得するために結合された認証の更新トークンを使用する場合、アクセス トークンは結合された認証を表し、レスポンスに含まれる任意の scope 値に使用できます。
    • 権限の組み合わせには、権限付与が別のクライアントからリクエストされた場合でも、ユーザーが API プロジェクトに付与したすべてのスコープが含まれます。たとえば、ユーザーがアプリケーションのデスクトップ クライアントを使用して一方のスコープへのアクセスを許可した後、モバイル クライアントを介して同じアプリケーションに別のスコープを付与した場合、統合された承認には両方のスコープが含まれます。
    • 複数の承認を組み合わせたトークンを取り消すと、関連するユーザーの代理での、その承認のすべてのスコープへのアクセスも同時に取り消されます。

    ステップ 1: 認証パラメータを設定するの言語固有のコードサンプルとステップ 2: Google の OAuth 2.0 サーバーにリダイレクトするのサンプルの HTTP / REST リダイレクト URL はすべて、増分認証を使用します。以下のコードサンプルは、増分認証を使用するために追加する必要があるコードも示しています。

    PHP

    $client->setIncludeGrantedScopes(true);

    Python

    Python では、include_granted_scopes キーワード引数を true に設定して、以前に付与したスコープが認証リクエストに含まれるようにします。次の例に示すように、設定したキーワード引数が include_granted_scopes だけとは限りません。

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

    Ruby

    auth_client.update!(
      :additional_parameters => {"include_granted_scopes" => "true"}
    )

    Node.js

    const authorizationUrl = oauth2Client.generateAuthUrl({
      // 'online' (default) or 'offline' (gets refresh_token)
      access_type: 'offline',
      /** Pass in the scopes array defined above.
        * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
      scope: scopes,
      // Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes: true
    });
    

    HTTP/REST

    GET https://accounts.google.com/o/oauth2/v2/auth?
      client_id=your_client_id&
      response_type=code&
      state=state_parameter_passthrough_value&
      scope=https%3A//www.googleapis.com/auth/drive.file&
      redirect_uri=https%3A//oauth2.example.com/code&
      prompt=consent&
      include_granted_scopes=true

    アクセス トークンの更新(オフライン アクセス)

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

    • Google API クライアント ライブラリを使用している場合、クライアント オブジェクトは、オフライン アクセス用にそのオブジェクトを構成する限り、必要に応じてアクセス トークンを更新します。
    • クライアント ライブラリを使用していない場合は、ユーザーを Google の OAuth 2.0 サーバーにリダイレクトするときに、access_type HTTP クエリ パラメータを offline に設定する必要があります。その場合、アクセス トークンと認証コードを交換すると、Google の承認サーバーが更新トークンを返します。アクセス トークンの有効期限が切れた場合(あるいはそれ以外の場合)は、更新トークンを使用して新しいアクセス トークンを取得できます。

    オフライン アクセスをリクエストすることは、ユーザーが存在しないときに Google API にアクセスする必要があるアプリケーションで必要です。たとえば、バックアップ サービスや所定の時間にアクションを実行するアプリは、ユーザーが存在しないときにアクセス トークンを更新できる必要があります。デフォルトのアクセス スタイルは online です。

    サーバー側ウェブ アプリケーション、インストールされているアプリケーション、デバイスはすべて、承認プロセス中に更新トークンを取得します。更新トークンは通常、クライアント側(JavaScript)ウェブ アプリケーションでは使用されません。

    PHP

    アプリケーションが Google API にオフラインでアクセスする必要がある場合は、API クライアントのアクセスタイプを offline に設定します。

    $client->setAccessType("offline");

    ユーザーがリクエストされたスコープへのオフライン アクセスを許可した後、ユーザーがオフラインのときにも引き続き API クライアントを使用してユーザーに代わって Google API にアクセスできます。クライアント オブジェクトは、必要に応じてアクセス トークンを更新します。

    Python

    Python で、access_type キーワード引数を offline に設定して、ユーザーに再度権限を要求せずにアクセス トークンを更新できるようにします。次の例に示すように、設定したキーワード引数が access_type だけとは限りません。

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

    ユーザーがリクエストされたスコープへのオフライン アクセスを許可した後、ユーザーがオフラインのときにも引き続き API クライアントを使用してユーザーに代わって Google API にアクセスできます。クライアント オブジェクトは、必要に応じてアクセス トークンを更新します。

    Ruby

    アプリケーションが Google API にオフラインでアクセスする必要がある場合は、API クライアントのアクセスタイプを offline に設定します。

    auth_client.update!(
      :additional_parameters => {"access_type" => "offline"}
    )

    ユーザーがリクエストされたスコープへのオフライン アクセスを許可した後、ユーザーがオフラインのときにも引き続き API クライアントを使用してユーザーに代わって Google API にアクセスできます。クライアント オブジェクトは、必要に応じてアクセス トークンを更新します。

    Node.js

    アプリケーションが Google API にオフラインでアクセスする必要がある場合は、API クライアントのアクセスタイプを offline に設定します。

    const authorizationUrl = oauth2Client.generateAuthUrl({
      // 'online' (default) or 'offline' (gets refresh_token)
      access_type: 'offline',
      /** Pass in the scopes array defined above.
        * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
      scope: scopes,
      // Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes: true
    });
    

    ユーザーがリクエストされたスコープへのオフライン アクセスを許可した後、ユーザーがオフラインのときにも引き続き API クライアントを使用してユーザーに代わって Google API にアクセスできます。クライアント オブジェクトは、必要に応じてアクセス トークンを更新します。

    アクセス トークンには有効期限があります。このライブラリは、更新トークンが期限切れになる前に、自動的に更新トークンを使用して新しいアクセス トークンを取得します。常に最新のトークンを保存する簡単な方法は、トークン イベントを使用することです。

    oauth2Client.on('tokens', (tokens) => {
      if (tokens.refresh_token) {
        // store the refresh_token in your secure persistent database
        console.log(tokens.refresh_token);
      }
      console.log(tokens.access_token);
    });

    このトークン イベントは最初の承認でのみ発生します。更新トークンを受信するために generateAuthUrl メソッドを呼び出すときには、access_typeoffline に設定する必要があります。更新トークンを受信するための適切な制約を設定せずにアプリに付与した権限をすでに付与している場合は、新しい更新トークンを受信するようにアプリを再承認する必要があります。

    後で refresh_token を設定するには、setCredentials メソッドを使用します。

    oauth2Client.setCredentials({
      refresh_token: `STORED_REFRESH_TOKEN`
    });
    

    クライアントが更新トークンを取得すると、アクセス トークンが取得され、次回の API 呼び出しで自動的に更新されます。

    HTTP/REST

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

    フィールド
    client_id API Consoleから取得したクライアント ID。
    client_secret API Consoleから取得したクライアント シークレット。
    grant_type OAuth 2.0 仕様で定義されているように、このフィールドの値は refresh_token に設定する必要があります。
    refresh_token 認証コード交換から返された更新トークン。

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

    POST /token HTTP/1.1
    Host: oauth2.googleapis.com
    Content-Type: application/x-www-form-urlencoded
    
    client_id=your_client_id&
    client_secret=your_client_secret&
    refresh_token=refresh_token&
    grant_type=refresh_token

    ユーザーがアプリケーションに付与されているアクセス権を取り消していない限り、トークン サーバーは新しいアクセス トークンを含む JSON オブジェクトを返します。次のスニペットはサンプル レスポンスを示しています。

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

    発行される更新トークンの数には上限があります。つまり、クライアントとユーザーの組み合わせごとに 1 つずつ、すべてのクライアントに対して 1 つのユーザー上限があります。更新トークンは長期保存のために保存し、有効な限り継続的に使用する必要があります。アプリケーションが更新トークンが多すぎると、これらの制限に達し、古い更新トークンが機能しなくなります。

    トークンの取り消し

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

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

    PHP

    プログラムでトークンを取り消すには、revokeToken() を呼び出します。

    $client->revokeToken();

    Python

    プログラムでトークンを取り消すには、パラメータとしてトークンを含めた https://oauth2.googleapis.com/revoke ヘッダーに Content-Type ヘッダーを設定します。

    requests.post('https://oauth2.googleapis.com/revoke',
        params={'token': credentials.token},
        headers = {'content-type': 'application/x-www-form-urlencoded'})

    Ruby

    プログラムでトークンを取り消すには、oauth2.revoke エンドポイントに対して HTTP リクエストを行います。

    uri = URI('https://oauth2.googleapis.com/revoke')
    response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)
    

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

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

    Node.js

    プログラムでトークンを取り消すには、/revoke エンドポイントに対して HTTPS POST リクエストを行います。

    const https = require('https');
    
    // Build the string for the POST request
    let postData = "token=" + userCredential.access_token;
    
    // Options for POST request to Google's OAuth 2.0 server to revoke a token
    let postOptions = {
      host: 'oauth2.googleapis.com',
      port: '443',
      path: '/revoke',
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': Buffer.byteLength(postData)
      }
    };
    
    // Set up the request
    const postReq = https.request(postOptions, function (res) {
      res.setEncoding('utf8');
      res.on('data', d => {
        console.log('Response: ' + d);
      });
    });
    
    postReq.on('error', error => {
      console.log(error)
    });
    
    // Post the request with data
    postReq.write(postData);
    postReq.end();
    

    トークン パラメータには、アクセス トークンまたは更新トークンを使用できます。トークンがアクセス トークンであり、対応する更新トークンがある場合、更新トークンも取り消されます。

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

    HTTP/REST

    プログラムでトークンを取り消すには、アプリケーションで 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 がエラーコードとともに返されます。