ウェブサーバー アプリケーションに 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 にアクセスできます。

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

クライアント ライブラリ

このページの言語固有の例では、Google API クライアント ライブラリを使用して OAuth 2.0 認証を実装します。コードサンプルを実行するには、使用する言語のクライアント ライブラリをインストールする必要があります。

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

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

Prerequisites

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

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

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

  1. Google API ConsoleのOpen the API Library
  2. If prompted, select a project, or create a new one.
  3. API Library 使用可能なすべての 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. フォームに必要事項を入力して [作成] をクリックします。PHP、Java、Python、Ruby、.NET などの言語やフレームワークを使用するアプリケーションでは、承認済みのリダイレクト URI を指定する必要があります。リダイレクト URI は、OAuth 2.0 サーバーがレスポンスを送信できるエンドポイントです。これらのエンドポイントは、Google の検証ルールを遵守している必要があります。

    テストでは、ローカルマシンを参照する URI(http://localhost:8080 など)を指定できます。以下のサンプルでは、リダイレクト URI として http://localhost:8080 を使用しています。

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

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

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

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

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

また、アプリケーションは承認の範囲内で認可スコープへのアクセスをリクエストすることを推奨します。このプロセスでは、アプリケーションは状況に応じたユーザーデータへのアクセス権をリクエストします。このベスト プラクティスは、アプリケーションがリクエストしているアクセス権を必要とする理由をより簡単に理解するのに役立ちます。

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

言語固有の要件

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

PHP

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

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

    composer require google/apiclient:^2.10

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 サーバーがユーザーをリダイレクトする場所を決定します。この値は、クライアントの API ConsoleCredentials pageで構成した OAuth 2.0 クライアントの承認済みリダイレクト URI のいずれかと正確に一致している必要があります。この値が、指定された 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 認証サーバーにヒントを提供できます。サーバーはヒントを使用して、ログイン フォームのメール フィールドに事前入力するか、適切なマルチログイン セッションを選択することで、ログインフローを簡素化します。

パラメータ値をメールアドレスまたは sub ID に設定します。これは、ユーザーの Google 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 サーバーがユーザーをリダイレクトする場所を決定します。この値は、クライアントの API ConsoleCredentials pageで構成した OAuth 2.0 クライアントの承認済みリダイレクト URI のいずれかと正確に一致している必要があります。この値が、指定された 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 では、flow.authorization_url メソッドを呼び出す際にキーワード引数として access_type を指定して、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 では、flow.authorization_url メソッドを呼び出す際にキーワード引数として state を指定して、state パラメータを設定します。

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

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

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

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

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

パラメータ値をメールアドレスまたは sub ID に設定します。これは、ユーザーの Google ID と同等です。

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

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

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

Python では、flow.authorization_url メソッドを呼び出す際にキーワード引数として prompt を指定して、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
  }
)

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

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 サーバーがユーザーをリダイレクトする場所を決定します。この値は、クライアントの API ConsoleCredentials pageで構成した OAuth 2.0 クライアントの承認済みリダイレクト URI のいずれかと正確に一致している必要があります。この値が、指定された 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 認証サーバーにヒントを提供できます。サーバーはヒントを使用して、ログイン フォームのメール フィールドに事前入力するか、適切なマルチログイン セッションを選択することで、ログインフローを簡素化します。

パラメータ値をメールアドレスまたは sub ID に設定します。これは、ユーザーの Google 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 を作成したら、ユーザーをリダイレクトします。

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

ステップ 3: Google が同意を求める

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

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

エラー

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

admin_policy_enforced

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

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 プロジェクトの API ConsoleCredentials page に、指定された client_id のリダイレクト URI のいずれか。

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

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

Ruby

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

  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 形式のファイルリストを出力します。

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.10
  4. 以下の内容で、ファイル index.phpoauth2callback.php を作成します。
  5. PHP を提供するように構成されたウェブサーバーで、サンプルを実行します。PHP 5.6 以降を使用している場合は、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 リクエストを送信する権限をリクエストします。
  • 現在の認証情報を取り消す: このリンクは、ユーザーがすでにアプリケーションに許可した権限を取り消すページを指しています。
  • Clear Flask session credentials: このリンクは、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 は、これらのルールに準拠している必要があります。後述する domain、host、path、query、scheme、userinfo の定義については、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 にオープン リダイレクトを含めることはできません。

    Fragment

    リダイレクト 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 つのスコープへのアクセスを許可してから、モバイル クライアント経由で同じアプリケーションに別のスコープを許可した場合、統合された承認には両方のスコープが含まれます。
    • 統合された承認を表すトークンを取り消すと、関連するユーザーに代わって、その承認のすべてのスコープへのアクセスが同時に取り消されます。

    ステップ 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 つ、すべてのクライアントで 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();
    

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

    取り消しが正常に処理されると、レスポンスのステータス コードは 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 とエラーコードが返されます。