ウェブサーバー アプリケーションに 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 APIs を呼び出す場合です。ウェブサーバー アプリケーションでは、サービス アカウントをユーザー承認と組み合わせて使用できます。

クライアント ライブラリ

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

Google API クライアント ライブラリを使用してアプリケーションの OAuth 2.0 フローを処理すると、クライアント ライブラリは多くのアクションを実行しますが、これらのアクションを使用しない場合はアプリケーションが独自に処理する必要があります。たとえば、保存されているアクセス トークンをアプリケーションでいつ使用または更新できるか、アプリケーションがいつ同意を再取得する必要があるかを判断します。また、クライアント ライブラリは正しいリダイレクト URL を生成し、認証コードをアクセス トークンと交換するリダイレクト ハンドラの実装を支援します。

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

Prerequisites

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

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

プロジェクトで 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 がリストに表示されない場合は、検索を使用して探すか、その 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 の検証ルールに準拠している必要があります。

    テストでは、http://localhost:8080 など、ローカルマシンを参照する URI を指定できます。なお、このドキュメントのすべての例で、リダイレクト 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.6 以降
  • Ruby 用の Google 認証ライブラリ:

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

    gem install sinatra

Node.js

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

  • Node.js のメンテナンス LTS、アクティブな LTS、現在のリリースのいずれか。
  • 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 ファイルからの情報を使用してアプリケーションを識別します。(このファイルの詳細については、認証情報の作成をご覧ください)。また、このオブジェクトによって、アプリケーションがアクセス権限をリクエストしているスコープと、Google の OAuth 2.0 サーバーからのレスポンスを処理するアプリケーションの認可エンドポイントへの URL も特定されます。最後に、このコードはオプションの 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" will prompt the user for consent
$client->setPrompt('consent');
$client->setIncludeGrantedScopes(true);   // incremental auth

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

パラメータ
client_id 必須

アプリケーションのクライアント ID。この値は API Console Credentials 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 識別子に設定します。

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

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

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

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

$client->setPrompt('consent');

表示される値は次のとおりです。

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

Python

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

このコードは Flow オブジェクトを作成します。このオブジェクトは、認証情報の作成後にダウンロードした client_secret.json ファイルの情報を使用してアプリケーションを識別します。このオブジェクトは、アプリケーションがアクセス権限をリクエストしているスコープと、Google の OAuth 2.0 サーバーからのレスポンスを処理するアプリケーションの認可エンドポイントへの URL も特定します。最後に、このコードはオプションの 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 Console Credentials 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 では、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 認証サーバーにヒントを提供できます。サーバーはこのヒントを使用して、ログイン フォームのメール フィールドに事前入力するか、適切なマルチログイン セッションを選択することで、ログインフローを簡素化します。

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

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_v3'
require "googleauth"
require 'googleauth/stores/redis_token_store'

client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json')
scope = 'https://www.googleapis.com/auth/drive.metadata.readonly'
token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, '/oauth2callback')

Your application uses the client object to perform OAuth 2.0 operations, such as generating authorization request URLs and applying access tokens to HTTP requests.

Node.js

The code snippet below creates a google.auth.OAuth2 object, which defines the parameters in the authorization request.

That object uses information from your client_secret.json file to identify your application. To ask for permissions from a user to retrieve an access token, you redirect them to a consent page. To create a consent page 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 Console Credentials 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 識別子に設定します。

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 = authorizer.get_authorization_url(login_hint: user_id, request: request)
  2. ユーザーを auth_uri にリダイレクトします。

Node.js

  1. ステップ 1 で生成された URL(authorizationUrl)の generateAuthUrl メソッドを使用して、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 アカウントは、Google Workspace 管理者のポリシーにより、リクエストされた 1 つ以上のスコープを承認できません。OAuth クライアント ID に明示的にアクセス権が付与されるまで、管理者がすべてのスコープまたは機密性の高いスコープおよび制限付きスコープへのアクセスを制限する方法については、Google Workspace 管理者のヘルプ記事の Google Workspace データにアクセスするサードパーティ製アプリと内部アプリを制御するをご覧ください。

disallowed_useragent

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

Android

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

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

iOS

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

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

org_internal

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

invalid_client

OAuth クライアント シークレットが正しくない。このリクエストに使用されたクライアント ID やシークレットなど、OAuth クライアントの構成を確認します。

invalid_grant

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

redirect_uri_mismatch

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

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

invalid_request

リクエストした内容に問題がありました。これにはいくつかの理由が考えられます。

  • リクエストの形式が正しくありません
  • リクエストに必須パラメータがありません
  • リクエストで、Google がサポートしていない認証方法が使用されています。OAuth 統合で推奨の統合方法が使用されていることを確認する

ステップ 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 をクリックすると、このフローをテストできます。この 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

コールバック ページで、googleauth ライブラリを使用して認可サーバーのレスポンスを確認します。authorizer.handle_auth_callback_deferred メソッドを使用して認証コードを保存し、最初に認可をリクエストした URL にリダイレクトします。これにより、ユーザーのセッションに結果が一時的に保存されるため、コードの交換が延期されます。

  target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
  redirect target_url

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から取得した API Consoleクライアント ID。
client_secret Credentials pageから取得した API Consoleクライアント シークレット。
code 最初のリクエストから返された認証コード。
grant_type OAuth 2.0 仕様で定義されているように、このフィールドの値は authorization_code に設定する必要があります。
redirect_uri 指定された client_id の API Console Credentials page でプロジェクトに対して一覧表示されたリダイレクト 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"
}

エラー

アクセス トークンの認証コードを交換すると、想定されるレスポンスではなく、次のエラーが発生することがあります。一般的なエラーコードと推奨の解決策を以下に示します。

invalid_grant

指定された認証コードが無効であるか、形式が正しくありません。OAuth プロセスを再起動して新しいコードをリクエストし、ユーザーに同意を再度求めます。

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

Ruby

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

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

または、メソッドに options パラメータを指定して、メソッドごとに承認を提供することもできます。

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

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 の呼び出しなど)。

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

HTTP GET の例

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

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

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

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

curl の例

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

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

または、クエリ文字列パラメータ オプション:

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

完全なサンプルコード

次の例では、ユーザーが認証を行い、アプリケーションがユーザーのドライブ メタデータにアクセスすることに同意した後、ユーザーの 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.php ファイルと oauth2callback.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 リクエストを送信する権限をリクエストします。
  • 現在の認証情報を取り消す: このリンクは、ユーザーがすでにアプリケーションに付与している権限を 取り消すページにリンクしています。
  • 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_v3'
require 'sinatra'
require 'googleauth'
require 'googleauth/stores/redis_token_store'

configure do
  enable :sessions

  set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json')
  set :scope, Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY
  set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
  set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, '/oauth2callback')
end

get '/' do
  user_id = settings.client_id.id
  credentials = settings.authorizer.get_credentials(user_id, request)
  if credentials.nil?
    redirect settings.authorizer.get_authorization_url(login_hint: user_id, request: request)
  end
  drive = Google::Apis::DriveV3::DriveService.new
  files = drive.list_files(options: { authorization: credentials })
  "<pre>#{JSON.pretty_generate(files.to_h)}</pre>"
end

get '/oauth2callback' do
  target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
  redirect target_url
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 は、以下のルールに準拠している必要があります。下記のドメイン、ホスト、パス、クエリ、スキーム、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” で終わる必要があります。
  • ユーザー情報

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

    [Path]

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

    クエリ

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

    Fragment

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

    キャラクター リダイレクト URI に次のような文字を含めることはできません。
    • ワイルドカード文字('*'
    • 印刷できない ASCII 文字
    • パーセント エンコードが無効です(パーセント記号の後に 2 桁の 16 進数が続く URL エンコード形式に従わない任意のパーセント エンコード)
    • 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 つの制限があります。更新トークンは長期間保存し、有効な間は継続して使用する必要があります。アプリケーションがリクエストする更新トークンが多すぎると、これらの制限に達することがあり、その場合は古い更新トークンが機能しなくなります。

    トークンの取り消し

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

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

    PHP

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

    $client->revokeToken();

    Python

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

    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 がエラーコードとともに返されます。