クライアントサイド ウェブ アプリケーション用の OAuth 2.0

このドキュメントでは、JavaScript ウェブ アプリケーションから Google API にアクセスするための OAuth 2.0 認証を実装する方法について説明します。OAuth 2.0 を使用すると、ユーザー名やパスワードなどの情報を秘密にしたまま、ユーザーが特定のデータをアプリケーションと共有できます。 たとえば、OAuth 2.0 を使用して、ユーザーの Google ドライブにファイルを保存する権限をアプリケーションで取得できます。

この OAuth 2.0 フローは暗黙的な権限付与フローと呼ばれます。これは、ユーザーがアプリを開いている間だけ API にアクセスするアプリ向けに設計されています。このようなアプリケーションでは、機密情報を保存することはできません。

このフローでは、アプリが Google URL を開きます。この URL では、クエリ パラメータを使用して、アプリとアプリが必要とする API アクセスのタイプを識別します。URL は、現在のブラウザ ウィンドウまたはポップアップで開くことができます。ユーザーは Google で認証を行い、リクエストされた権限を付与できます。その後、ユーザーをアプリにリダイレクトします。リダイレクトにはアクセス トークンが含まれます。アプリはこのトークンを確認し、API リクエストに使用します。

Google API クライアント ライブラリと Google Identity Services

JavaScript 用の Google API クライアント ライブラリを使用して Google に対して承認済みの呼び出しを行う場合は、 Google Identity Services JavaScript ライブラリを使用して OAuth 2.0 フローを処理する必要があります。Google ID サービスのトークンモデルをご覧ください。これは、OAuth 2.0 の暗黙的な権限付与フローに基づいています。

前提条件

プロジェクトで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. フォームに入力します。JavaScript を使用して承認済みの Google API リクエストを送信するアプリケーションでは、承認済みの JavaScript オリジンを指定する必要があります。オリジンは、アプリケーションが OAuth 2.0 サーバーにリクエストを送信できるドメインを識別します。これらのオリジンは、Google の検証ルールに準拠している必要があります。

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

スコープを使用すると、アプリケーションに必要なリソースへのアクセスのみをリクエストできます。また、ユーザーはアプリケーションに付与するアクセス権の範囲を制御できます。そのため、リクエストするスコープの数とユーザーの同意を得る可能性には逆相関関係がある場合があります。

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

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

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

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

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

ユーザーのデータにアクセスする権限をリクエストするには、ユーザーを Google の OAuth 2.0 サーバーにリダイレクトします。

OAuth 2.0 エンドポイント

Google の OAuth 2.0 エンドポイント(https://accounts.google.com/o/oauth2/v2/auth)からアクセスをリクエストするための URL を生成します。このエンドポイントには HTTPS でアクセスできます。プレーン HTTP 接続は拒否されます。

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

パラメータ
client_id 必須

アプリケーションのクライアント ID。この値は API Console Credentials pageで確認できます。

redirect_uri 必須

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

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

response_type 必須

JavaScript アプリケーションでは、このパラメータの値を token に設定する必要があります。この値は、認証プロセスの完了後にユーザーがリダイレクトされる URI(#)のフラグメント識別子に含まれる name=value ペアとしてアクセス トークンを返すよう Google 認可サーバーに指示します。

scope 必須

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

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

可能な限り、コンテキスト内で認可スコープへのアクセスをアプリケーションはリクエストすることをおすすめします。状況に応じてユーザーデータへのアクセスをリクエストする場合は、段階的な認証を介して、アプリケーションがアクセスを必要とする理由をユーザーが簡単に理解できるようにします。

state 推奨

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

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

include_granted_scopes 省略可

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

login_hint 省略可

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

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

prompt 省略可

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

指定できる値は次のとおりです。

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

Google の承認サーバーへのリダイレクトの例

次に、URL の例を示します。読みやすくするために改行とスペースを入れています。

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

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

JavaScript サンプルコード

次の JavaScript スニペットは、JavaScript 用の Google API クライアント ライブラリを使用せずに、JavaScript で認証フローを開始する方法を示しています。この OAuth 2.0 エンドポイントはクロスオリジン リソース シェアリング(CORS)をサポートしていないため、スニペットはそのエンドポイントへのリクエストを開くフォームを作成します。

/*
 * Create form to request access token from Google's OAuth 2.0 server.
 */
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

  // Create <form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);

  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client_id': 'YOUR_CLIENT_ID',
                'redirect_uri': 'YOUR_REDIRECT_URI',
                'response_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include_granted_scopes': 'true',
                'state': 'pass-through value'};

  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

ステップ 2: 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 の 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 同意画面を設定する」のユーザータイプのセクションをご覧ください。

invalid_client

リクエストの送信元が、このクライアントに対して承認されていません。origin_mismatch をご覧ください。

invalid_grant

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

origin_mismatch

認証リクエストを発信した JavaScript のスキーム、ドメイン、ポートが、OAuth クライアント ID に登録されている承認済みの JavaScript オリジン URI と一致しない場合があります。 Credentials pageで承認済みの JavaScript 生成元を Google API Console確認します。

redirect_uri_mismatch

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

認証リクエストを発信した JavaScript のスキーム、ドメイン、ポートが、OAuth クライアント ID に登録されている承認済みの JavaScript オリジン URI と一致しない場合があります。 Google API Console Credentials pageで承認済みの JavaScript 生成元を確認します。

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

invalid_request

リクエストに何か問題がありました。これにはさまざまな理由が考えられます。

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

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

OAuth 2.0 エンドポイント

OAuth 2.0 サーバーは、アクセス トークン リクエストで指定された redirect_uri にレスポンスを送信します。

ユーザーがリクエストを承認すると、レスポンスにアクセス トークンが含まれます。ユーザーがリクエストを承認しないと、レスポンスにエラー メッセージが格納されます。以下に示すように、アクセス トークンまたはエラー メッセージがリダイレクト URI のハッシュ フラグメントで返されます。

  • アクセス トークンのレスポンス:

    https://oauth2.example.com/callback#access_token=4/P7q7W91&token_type=Bearer&expires_in=3600

    access_token パラメータに加えて、フラグメント文字列には、常に Bearer に設定される token_type パラメータと、トークンの存続期間を秒単位で指定する expires_in パラメータも含まれます。state パラメータがアクセス トークン リクエストで指定された場合、その値もレスポンスに含まれます。

  • エラー レスポンス:
    https://oauth2.example.com/callback#error=access_denied

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

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

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

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

Google API の呼び出し

OAuth 2.0 エンドポイント

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

JavaScript サンプルコード

以下のコード スニペットは、CORS(クロスオリジン リソース シェアリング)を使用して Google API にリクエストを送信する方法を示しています。この例では、JavaScript 用の Google API クライアント ライブラリを使用しません。ただし、クライアント ライブラリを使用していない場合でも、そのライブラリのドキュメントにある CORS サポートのガイドが、これらのリクエストに関する理解を深めるのに役立ちます。

このコード スニペットでは、access_token 変数は、認可されたユーザーに代わって API リクエストを行うために取得したトークンを表します。完全なサンプルは、そのトークンをブラウザのローカル ストレージに格納し、API リクエストを行うときにトークンを取得する方法を示しています。

var xhr = new XMLHttpRequest();
xhr.open('GET',
    'https://www.googleapis.com/drive/v3/about?fields=user&' +
    'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
  console.log(xhr.response);
};
xhr.send(null);

完全なサンプルコード

OAuth 2.0 エンドポイント

このコードサンプルは、JavaScript 用の Google API クライアント ライブラリを使用せずに、JavaScript で OAuth 2.0 フローを完了する方法を示しています。このコードは、API リクエストを試すボタンを表示する HTML ページ用です。このボタンをクリックすると、API アクセス トークンがブラウザのローカル ストレージに保存されているかどうかがコードによってチェックされます。リクエストした場合は API リクエストを実行します。それ以外の場合は、OAuth 2.0 フローが開始されます。

OAuth 2.0 フローの場合、このページは次の手順を実行します。

  1. これにより、ユーザーは Google の OAuth 2.0 サーバーにリダイレクトされます。このサーバーは https://www.googleapis.com/auth/drive.metadata.readonly スコープへのアクセスをリクエストします。
  2. リクエストされた 1 つ以上のスコープへのアクセスを許可(または拒否)すると、ユーザーは元のページにリダイレクトされます。そのページで、フラグメント識別子文字列のアクセス トークンが解析されます。
  3. アクセス トークンを使用してサンプル API リクエストを作成します。

    API リクエストは、Drive API の about.get メソッドを呼び出して、承認済みユーザーの Google ドライブ アカウントに関する情報を取得します。

  4. リクエストが正常に実行されると、API レスポンスがブラウザのデバッグ コンソールに記録されます。

Google アカウントの [権限] ページで、アプリへのアクセス権を取り消すことができます。アプリは OAuth 2.0 Demo for Google API Docs として表示されます。

このコードをローカルで実行するには、認可認証情報に対応する YOUR_CLIENT_ID 変数と YOUR_REDIRECT_URI 変数の値を設定する必要があります。YOUR_REDIRECT_URI 変数は、ページが提供されるのと同じ URL に設定する必要があります。この値は、 API Console Credentials pageで構成した OAuth 2.0 クライアント用に承認済みのリダイレクト URI のいずれかと完全に一致している必要があります。この値が承認済みの URI と一致しない場合、redirect_uri_mismatch エラーが発生します。また、プロジェクトでこのリクエストに対して適切な API を有効にする必要があります。

<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*
   * Create form to request access token from Google's OAuth 2.0 server.
   */
  function oauth2SignIn() {
    // Google's OAuth 2.0 endpoint for requesting an access token
    var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

JavaScript 送信元の検証ルール

Google では、デベロッパーがアプリケーションの安全性を維持できるように、JavaScript のオリジンに次の検証ルールを適用しています。JavaScript のオリジンは、以下のルールに準拠している必要があります。後述のドメイン、ホスト、スキームの定義については、RFC 3986 のセクション 3 をご覧ください。

検証ルール
スキーム

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

ホスト

ホストに数値表記の IP アドレスを指定することはできません。ローカルホストの IP アドレスはこのルールから除外されます。

ドメイン
  • ホスト TLD(トップレベル ドメイン)は、パブリック サフィックス リストに属している必要があります。
  • ホストドメインを “googleusercontent.com” にすることはできません。
  • アプリがドメインを所有していない限り、JavaScript オリジンに短縮 URL ドメイン(goo.gl など)を含めることはできません。
  • ユーザー情報

    JavaScript オリジンに userinfo サブコンポーネントを含めることはできません。

    [Path]

    JavaScript オリジンにパス コンポーネントを含めることはできません。

    クエリ

    JavaScript オリジンにクエリ コンポーネントを含めることはできません。

    Fragment

    JavaScript オリジンにフラグメント コンポーネントを含めることはできません。

    文字数 JavaScript 生成元には、次のような特定の文字を含めることはできません。
    • ワイルドカード文字('*'
    • 印刷できない 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 つのスコープへのアクセスを許可し、その後、モバイル クライアントを介して同じアプリケーションに別のスコープを付与した場合、統合された承認には、両方のスコープが含まれます。
    • 統合された承認を表すトークンを取り消すと、関連するユーザーに代わってその承認のすべてのスコープに対するアクセス権が同時に取り消されます。

    以下のコードサンプルは、既存のアクセス トークンにスコープを追加する方法を示しています。このアプローチにより、アプリは複数のアクセス トークンを管理する必要がなくなります。

    OAuth 2.0 エンドポイント

    既存のアクセス トークンにスコープを追加するには、Google の OAuth 2.0 サーバーへのリクエストinclude_granted_scopes パラメータを含めます。

    次のコード スニペットは、その方法を示しています。このスニペットでは、アクセス トークンが有効なスコープがブラウザのローカル ストレージに保存されていることを前提としています。(完全なサンプルのコードでは、ブラウザのローカル ストレージに oauth2-test-params.scope プロパティを設定することで、アクセス トークンが有効になるスコープのリストを保存しています)。

    このスニペットは、アクセス トークンが有効なスコープと、特定のクエリに使用するスコープを比較します。アクセス トークンがそのスコープに含まれない場合、OAuth 2.0 フローが開始されます。ここで、oauth2SignIn 関数は、ステップ 2 で提供された関数と同じです(これは後ほど完全な例で説明します)。

    var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    
    var current_scope_granted = false;
    if (params.hasOwnProperty('scope')) {
      var scopes = params['scope'].split(' ');
      for (var s = 0; s < scopes.length; s++) {
        if (SCOPE == scopes[s]) {
          current_scope_granted = true;
        }
      }
    }
    
    if (!current_scope_granted) {
      oauth2SignIn(); // This function is defined elsewhere in this document.
    } else {
      // Since you already have access, you can proceed with the API request.
    }

    トークンの取り消し

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

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

    OAuth 2.0 エンドポイント

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

    次の JavaScript スニペットは、JavaScript 用 Google API クライアント ライブラリを使用せずに、JavaScript でトークンを取り消す方法を示しています。トークンを取り消すための Google の OAuth 2.0 エンドポイントはクロスオリジン リソース シェアリング(CORS)をサポートしていないため、コードは XMLHttpRequest() メソッドを使用してリクエストを送信するのではなく、フォームを作成してエンドポイントに送信します。

    function revokeAccess(accessToken) {
      // Google's OAuth 2.0 endpoint for revoking access tokens.
      var revokeTokenEndpoint = 'https://oauth2.googleapis.com/revoke';
    
      // Create <form> element to use to POST data to the OAuth 2.0 endpoint.
      var form = document.createElement('form');
      form.setAttribute('method', 'post');
      form.setAttribute('action', revokeTokenEndpoint);
    
      // Add access token to the form so it is set as value of 'token' parameter.
      // This corresponds to the sample curl request, where the URL is:
      //      https://oauth2.googleapis.com/revoke?token={token}
      var tokenField = document.createElement('input');
      tokenField.setAttribute('type', 'hidden');
      tokenField.setAttribute('name', 'token');
      tokenField.setAttribute('value', accessToken);
      form.appendChild(tokenField);
    
      // Add form to page and submit it to actually revoke the token.
      document.body.appendChild(form);
      form.submit();
    }