Google Identity Services に移行する

<ph type="x-smartling-placeholder">

概要

Google API を呼び出すためのユーザーごとのアクセス トークンを取得するために、Google は複数の JavaScript ライブラリ:

このガイドでは、これらのライブラリから Google Cloud Identity Services ライブラリ

このガイドに従うと、次のことができます。

  • 非推奨のプラットフォーム ライブラリを Identity Services ライブラリに置き換える および
  • API クライアント ライブラリを使用している場合は、非推奨の gapi.auth2 モジュールを削除します。 Identity Services の同等のメソッドに置き換えることができます。

Identity Services JavaScript の変更点についての説明 ライブラリで概要ユーザー認証の仕組みを読んで確認できます。 主な用語と概念について説明します。

ユーザーの登録とログインの認証については、以下をご覧ください。 Google ログインからの移行をご覧ください。

承認フローを特定する

考えられるユーザー承認フローには、暗黙的と認可の 2 つがあります。 できます。

ウェブアプリを確認して、現在の承認フローの種類を特定します。 見ていきましょう。

ウェブアプリが暗黙的フローを使用していることを示します。

ウェブアプリが認可コードフローを使用していることを示します。

  • 実装は以下に基づいて行われます。

  • アプリは、ユーザーのブラウザとバックエンド プラットフォームの両方で実行されます。

  • バックエンド プラットフォームは、認証コードのエンドポイントをホストします。

  • バックエンド プラットフォームは、ユーザーの代わりに Google API を呼び出します。このとき、 オフライン モードとも呼ばれます。

  • 更新トークンは、バックエンド プラットフォームによって管理、保存されます。

場合によっては、コードベースが両方のフローをサポートしていることもあります。

承認フローを選択する

移行を開始する前に、現在の状態のままで ニーズを最適に満たすためには、既存のフローを使用するか、別のフローを採用することをおすすめします。

承認フローの選択を確認して主な違いを理解する トレードオフについて見ていきます

ほとんどの場合、認証コードフローをおすすめします。認証コードフローでは、 最高レベルのユーザー セキュリティを提供します。このフローを実装することで 更新の取得などの新しいオフライン機能をより簡単に追加できる カレンダー、写真、定期購入、 できます。

以下のセレクタを使用して、承認フローを選択します。

暗黙的フロー

ユーザーが存在する間にブラウザ内で使用するアクセス トークンを取得します。

暗黙的フローの例では、移行前と移行後のウェブアプリを示しています。 Identity Services。

認可コードフロー

Google が発行したユーザーごとの認証コードがバックエンドに配信される プラットフォーム上でアクセス トークンと更新トークンと交換されます。

認可コードフローの例では、ウェブアプリを使用する前と使用した後のウェブアプリを示しています。 Identity Services への移行。

このガイドでは、太字の手順に従って追加、 既存の機能を削除更新置換します。

ブラウザ内ウェブアプリの変更

このセクションでは、ブラウザ内ウェブアプリに行う変更について説明します。 Google Identity Services JavaScript ライブラリに移行しました。

影響を受けるコードの特定とテスト

デバッグ Cookie は、影響を受けるコードの特定やサポート終了後のテストに役立ちます。 確認します。

大規模または複雑なアプリでは、影響を受けるすべてのコードを gapi.auth2 モジュールのサポート終了。近日中にリリースされる予定 追加するには、環境変数の値に G_AUTH2_MIGRATION の Cookie を informational に設定。必要に応じて、コロンと セッション ストレージにもロギングします。ログイン後 収集したログをバックエンドに送信して 後で確認できるように 分析できますたとえば、informational:showauth2use はオリジンと URL を showauth2use という名前のセッション ストレージ キー。

gapi.auth2 モジュールが読み込まれなくなったときのアプリの動作を確認するには、 G_AUTH2_MIGRATION Cookie の値を enforced に設定します。これにより 必要があります。

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

  • enforced gapi.auth2 モジュールをロードしない。
  • informational 非推奨の機能の使用を JS コンソールに記録します。さらに記録する オプションのキー名が設定されている場合は、 informational:key-name

ユーザーへの影響を最小限に抑えるため、この Cookie は最初にローカルに設定することをおすすめします。 を使用することです。

ライブラリとモジュール

gapi.auth2 モジュールは、ログインのユーザー認証と暗黙のユーザー認証を管理します。 使用する代わりに、このモジュールの後継で、そのオブジェクトと Google Identity Services ライブラリを使用できます。

Identity Services ライブラリをウェブアプリに追加する( ドキュメント:

<script src="https://accounts.google.com/gsi/client" async defer></script>

gapi.load('auth2', function) を使用して auth2 モジュールを読み込むインスタンスを削除します。

Google Identity Services ライブラリは、gapi.auth2 モジュールに代わるものです。 Google API の gapi.client モジュールを引き続き使用できます。 JavaScript 用のクライアント ライブラリを使用して、自動作成機能を活用する 複数の API 呼び出しをバッチ処理し、 CORS 管理機能が含まれています

クッキー

ユーザー認証に Cookie の使用は必要ありません。

ユーザー認証について詳しくは、Google ログインからの移行をご覧ください。 Google による Cookie の使用、Google による Cookie の使用など、 Google のプロダクトやサービス

認証情報

Google Identity Services は、ユーザーの認証と認可を 2 つの異なるオペレーションで、ユーザー認証情報は別個のものです。つまり、ユーザー認証情報は、 アクセス トークンとは別個に返されますが、 あります。

これらの変更を確認するには、認証情報の例をご覧ください。

暗黙的フロー

ユーザー プロファイルを削除してユーザー認証と認可を分離する 認証フローからの処理。

次の Google ログイン JavaScript クライアント リファレンス削除します。

メソッド

  • GoogleUser.getBasicProfile()
  • GoogleUser.getId()

認可コードフロー

Identity Services は、ブラウザ内の認証情報を ID トークンとアクセス あります。この変更は、直接契約で取得したクルデンシャルには適用されません。 Google OAuth 2.0 エンドポイントに対する呼び出しや、 Google Cloud Storage などのプラットフォーム上の API Node.js クライアント

セッション状態

これまで、Google ログインでは以下を使用してユーザーのログイン ステータスを管理できました。

ウェブへのログイン状態とユーザー セッションの管理はお客様の責任で行っていただく必要があります 。

次の Google ログイン JavaScript クライアント リファレンス削除します。

オブジェクト:

  • gapi.auth2.SignInOptions

メソッド:

  • GoogleAuth.attachClickHandler()
  • GoogleAuth.isSignedIn()
  • GoogleAuth.isSignedIn.get()
  • GoogleAuth.isSignedIn.listen()
  • GoogleAuth.signIn()
  • GoogleAuth.signOut()
  • GoogleAuth.currentUser.get()
  • GoogleAuth.currentUser.listen()
  • GoogleUser.isSignedIn()

クライアントの構成

ウェブアプリを更新して、暗黙的または 認証コードフローについて説明します。

次の Google ログイン JavaScript クライアント リファレンス削除します。

オブジェクト:

  • gapi.auth2.ClientConfig
  • gapi.auth2.OfflineAccessOptions

メソッド:

  • gapi.auth2.getAuthInstance()
  • GoogleUser.grant()

暗黙的フロー

TokenClientConfig オブジェクトと initTokenClient() 呼び出しを追加: トークンの初期化のサンプルに従って、ウェブアプリを構成します。 できます

Google ログイン JavaScript クライアント リファレンスGoogle ID サービス:

オブジェクト:

  • TokenClientConfiggapi.auth2.AuthorizeConfig

メソッド:

  • google.accounts.oauth2.initTokenClient()gapi.auth2.init()

パラメータ:

  • gapi.auth2.AuthorizeConfig.login_hintTokenClientConfig.login_hint
  • gapi.auth2.GoogleUser.getHostedDomain(): TokenClientConfig.hd

認可コードフロー

CodeClientConfig オブジェクトと initCodeClient() 呼び出しを追加して構成する コード クライアントを初期化するの例に沿ってウェブアプリをテストします。

暗黙的フローから認可コードフローに切り替える場合:

Google ログイン JavaScript クライアント リファレンスを削除する

オブジェクト:

  • gapi.auth2.AuthorizeConfig

メソッド:

  • gapi.auth2.init()

パラメータ:

  • gapi.auth2.AuthorizeConfig.login_hint
  • gapi.auth2.GoogleUser.getHostedDomain()

トークン リクエスト

ボタンのクリックなどのユーザー操作によってリクエストが生成され、 暗黙的なトークンでユーザーのブラウザに直接返される ユーザーごとの認証コードを交換した後、バックエンド プラットフォームに アクセストークンと更新トークンの 両方が必要です

暗黙的フロー

ユーザーがブラウザでアクセス トークンを取得し、 Google とのアクティブなセッションがある。暗黙的モードでは アクセス トークンをリクエストするには、以前に リクエストできます。

Google ログイン JavaScript クライアント リファレンス: Google ID サービス:

メソッド:

  • TokenClient.requestAccessToken()gapi.auth2.authorize()
  • GoogleUser.reloadAuthResponse()TokenClient.requestAccessToken()

リンクまたはボタンを追加して requestAccessToken() を呼び出し、 ポップアップ UX フローでアクセス トークンをリクエストしたり、新しいトークンが トークンが期限切れになります。

コードベースを次のように更新します。

  • requestAccessToken()OAuth 2.0 トークンフローをトリガーします。
  • requestAccessToken を使用して増分認可をサポートする。 OverridableTokenClientConfig で、多数のスコープに対して 1 つのリクエストを分離する 分割する方法です
  • 既存のトークンが期限切れになるか、取り消されたときに新しいトークンをリクエストします。

複数のスコープを操作するには、コードベースに対する構造的な変更が必要になる場合があります スコープへのアクセスを、一度にすべてではなく、必要なときにだけリクエストするようにします。 これは増分認可と呼ばれます各リクエストには、 スコープは 1 つにすることをおすすめします。お客様への対応方法を確認 、アプリを更新して増分を追加する方法について詳しくは、 あります。

アクセス トークンの有効期限が切れると、gapi.auth2 モジュールは自動的にトークンを取得します。 新しい有効なアクセス トークンを作成します。ユーザーのセキュリティを強化するため、 トークンの自動更新プロセスは Google Identity ではサポートされていません サービス ライブラリ。期限切れのアクセスを検出するには、ウェブアプリを更新する必要があります 新しいトークンをリクエストします。詳細については、以下のトークン処理セクションをご覧ください。

認可コードフロー

requestCode() を呼び出して承認をリクエストするリンクまたはボタンを追加します 提供します。例については、OAuth 2.0 コードフローをトリガーするをご覧ください。

レスポンスへの応答方法の詳細については、以下のトークン処理に関するセクションをご覧ください。 アクセス トークンの有効期限が切れた、または取り消された。

トークンの処理

期限切れになった、または期限切れになったときに失敗した Google API 呼び出しを検出するエラー処理を追加 アクセス トークンが使用され、新しい有効なアクセス トークンがリクエストされます。

HTTP ステータス コード 401 Unauthorizedinvalid_token のエラー メッセージ: 期限切れになった、または取り消されたアクセス トークンが使用されたときに、Google API から返されます。たとえば、 例については、無効なトークン レスポンスをご覧ください。

期限切れのトークン

アクセス トークンの有効期間は短く、多くの場合、有効期間は数分です。

トークンの取り消し

Google アカウントの所有者は、以前に許可した同意をいつでも取り消すことができます。行うこと 既存のアクセス トークンと更新トークンを無効にします。取り消しは次のいずれかに revoke() を使用してプラットフォームからトリガーするか、Google アカウント

Google ログイン JavaScript クライアント リファレンス: Google ID サービス:

メソッド:

  • google.accounts.oauth2.revoke()getAuthInstance().disconnect()
  • google.accounts.oauth2.revoke()GoogleUser.disconnect()

ユーザーがプラットフォームでアカウントを削除した場合、revoke を呼び出す。 が、アプリとのデータ共有に対する同意の取り消しを求めています。

ウェブアプリとバックエンドの両方で アクセス トークンをリクエストします。同意ダイアログの表示例を見る ユーザーに提供します

アプリにアクセス トークンを発行する前に、既存の有効な Google ユーザーの同意を求め、結果を記録するには、セッションが必要です。ユーザー Google アカウントへのログインを求められることがあります。これは、既存のセッションで 必要があります。

ユーザーのログイン

ユーザーは別のブラウザタブで Google アカウントにログインするか、 アクセスする必要がありますログイン名 Google からお客様のサイトにアクセスして、Google アカウント間のアクティブなセッションが確立される ユーザーが初めてアプリを開いたときこれにより、 メリット:

  • ユーザーがアクセスをリクエストしてログインしなければならない回数を最小限に抑える アクティブなセッションで Google アカウントのログイン プロセスが開始されると、トークンによって Google アカウントのログイン プロセスが開始されます。 作成します。
  • JWT ID トークンの credential email フィールドを次の値として直接使用します。 CodeClientConfig または TokenClientConfiglogin_hint パラメータ 説明します。これは、プラットフォームで API の互換性が維持されていない場合に特に便利です。 ユーザー アカウント管理システムなどです。
  • Google アカウントを検索し、 プラットフォーム上で重複するアカウントを最小限に抑えることができます。
  • 新しいローカル アカウントが作成されたら、登録ダイアログとフローを ユーザー認証ダイアログやフローから明確に分離されているため、 必要な手順の数、離脱率の改善。

ログイン後、アクセス トークンの発行前にユーザーは同意する必要があります アプリケーションのスコープを指定します。

同意後、アクセス トークンと承認済みのスコープのリストが返されます 拒否または拒否されます

きめ細かい権限により、ユーザーは個々のスコープを承認または拒否できます。日時 アクセスをリクエストした場合、各スコープは付与または拒否されます。 他のスコープに依存しませんユーザーの選択に基づいてアプリを選択 個々のスコープに依存する機能が有効になります。

暗黙的フロー

Google ログイン JavaScript クライアント リファレンスGoogle ID サービス:

オブジェクト:

  • TokenClient.TokenResponsegapi.auth2.AuthorizeResponse
  • TokenClient.TokenResponsegapi.auth2.AuthResponse

メソッド:

  • GoogleUser.hasGrantedScopes()google.accounts.oauth2.hasGrantedAllScopes()
  • GoogleUser.getGrantedScopes()google.accounts.oauth2.hasGrantedAllScopes()

Google ログイン JavaScript のクライアント リファレンス削除します。

メソッド:

  • GoogleUser.getAuthResponse()

hasGrantedAllScopes() を使用してウェブアプリを更新し、 こちらのきめ細かい権限の例に沿って hasGrantedAnyScope() を作成します。

認可コードフロー

認証コード エンドポイントをバックエンドに更新または追加する 認証コードの処理の手順に沿って、認証プラットフォームを認証します。

プラットフォームを更新し、コードを使用する リクエストを検証し、アクセス トークンを取得して更新するためのモデルガイド あります。

プラットフォームを更新して、機能を選択的に有効または無効にします。 ユーザーが承認した個々のスコープに基づいて、 段階的承認の手順に沿って、Google で ユーザーによって付与されたアクセス スコープ

暗黙的フローの例

従来の方法

GAPI クライアント ライブラリ

JavaScript の Google API クライアント ライブラリの例 ユーザーの同意を求めるポップアップ ダイアログを使用してブラウザで実行されている。

gapi.auth2 モジュールは自動的に読み込まれて使用されます。 gapi.client.init() などを非表示にします。

<!DOCTYPE html>
  <html>
    <head>
      <script src="https://apis.google.com/js/api.js"></script>
      <script>
        function start() {
          gapi.client.init({
            'apiKey': 'YOUR_API_KEY',
            'clientId': 'YOUR_CLIENT_ID',
            'scope': 'https://www.googleapis.com/auth/cloud-translation',
            'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
          }).then(function() {
            // Execute an API request which is returned as a Promise.
            // The method name language.translations.list comes from the API discovery.
            return gapi.client.language.translations.list({
              q: 'hello world',
              source: 'en',
              target: 'de',
            });
          }).then(function(response) {
            console.log(response.result.data.translations[0].translatedText);
          }, function(reason) {
            console.log('Error: ' + reason.result.error.message);
          });
        };

        // Load the JavaScript client library and invoke start afterwards.
        gapi.load('client', start);
      </script>
    </head>
    <body>
      <div id="results"></div>
    </body>
  </html>

JS クライアント ライブラリ

クライアントサイド ウェブ アプリケーション用の OAuth 2.0 ユーザーの同意を求めるポップアップ ダイアログが表示されます。

gapi.auth2 モジュールは手動で読み込まれます。

<!DOCTYPE html>
<html><head></head><body>
<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from API Console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>

OAuth 2.0 エンドポイント

クライアントサイド ウェブ アプリケーション用の OAuth 2.0 ユーザーの同意のために Google にリダイレクトされる。

この例は、ネットワークから Google の OAuth 2.0 エンドポイントへの直接呼び出しを示しています。 gapi.auth2 モジュールや JavaScript を使用していないユーザーのブラウザ ライブラリです。

<!DOCTYPE html>
<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>

新しい方法

GIS のみ

この例は、Google Identity Service の JavaScript ライブラリのみを示しています。 トークンモデルを使用し、ユーザーの同意を求めるポップアップ ダイアログを表示します。内容 構成に必要な最小限の手順を示すために、 アクセス トークンをリクエストして取得し、Google API を呼び出すだけです。

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      var access_token;

      function initClient() {
        client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/contacts.readonly',
          callback: (tokenResponse) => {
            access_token = tokenResponse.access_token;
          },
        });
      }
      function getToken() {
        client.requestAccessToken();
      }
      function revokeToken() {
        google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
      }
      function loadCalendar() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
        xhr.send();
      }
    </script>
    <h1>Google Identity Services Authorization Token model</h1>
    <button onclick="getToken();">Get access token</button><br><br>
    <button onclick="loadCalendar();">Load Calendar</button><br><br>
    <button onclick="revokeToken();">Revoke token</button>
  </body>
</html>

GAPI async/await

この例では、 トークンモデルを作成し、gapi.auth2 モジュールを削除し、 JavaScript の Google API クライアント ライブラリ

Promise、async、await は、ライブラリの読み込み順序を強制し、 認可エラーを検出して再試行します。API 呼び出しは、有効なリソースが 使用できます。

ユーザーはアクセス トークンが ページが最初に読み込まれたとき、またはアクセス トークンの後に読み込まれたときにのみ見当たらない の有効期限が切れています。

<!DOCTYPE html>
<html>
<head></head>
<body>
  <h1>GAPI with GIS async/await</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>

  <script>

    const gapiLoadPromise = new Promise((resolve, reject) => {
      gapiLoadOkay = resolve;
      gapiLoadFail = reject;
    });
    const gisLoadPromise = new Promise((resolve, reject) => {
      gisLoadOkay = resolve;
      gisLoadFail = reject;
    });

    var tokenClient;

    (async () => {
      document.getElementById("showEventsBtn").style.visibility="hidden";
      document.getElementById("revokeBtn").style.visibility="hidden";

      // First, load and initialize the gapi.client
      await gapiLoadPromise;
      await new Promise((resolve, reject) => {
        // NOTE: the 'auth2' module is no longer loaded.
        gapi.load('client', {callback: resolve, onerror: reject});
      });
      await gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
      });

      // Now load the GIS client
      await gisLoadPromise;
      await new Promise((resolve, reject) => {
        try {
          tokenClient = google.accounts.oauth2.initTokenClient({
              client_id: 'YOUR_CLIENT_ID',
              scope: 'https://www.googleapis.com/auth/calendar.readonly',
              prompt: 'consent',
              callback: '',  // defined at request time in await/promise scope.
          });
          resolve();
        } catch (err) {
          reject(err);
        }
      });

      document.getElementById("showEventsBtn").style.visibility="visible";
      document.getElementById("revokeBtn").style.visibility="visible";
    })();

    async function getToken(err) {

      if (err.result.error.code == 401 || (err.result.error.code == 403) &&
          (err.result.error.status == "PERMISSION_DENIED")) {

        // The access token is missing, invalid, or expired, prompt for user consent to obtain one.
        await new Promise((resolve, reject) => {
          try {
            // Settle this promise in the response callback for requestAccessToken()
            tokenClient.callback = (resp) => {
              if (resp.error !== undefined) {
                reject(resp);
              }
              // GIS has automatically updated gapi.client with the newly issued access token.
              console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
              resolve(resp);
            };
            tokenClient.requestAccessToken();
          } catch (err) {
            console.log(err)
          }
        });
      } else {
        // Errors unrelated to authorization: server errors, exceeding quota, bad requests, and so on.
        throw new Error(err);
      }
    }

    function showEvents() {

      // Try to fetch a list of Calendar events. If a valid access token is needed,
      // prompt to obtain one and then retry the original request.
      gapi.client.calendar.events.list({ 'calendarId': 'primary' })
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => getToken(err))  // for authorization errors obtain an access token
      .then(retry => gapi.client.calendar.events.list({ 'calendarId': 'primary' }))
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => console.log(err)); // cancelled by user, timeout, etc.
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
      }
    }

  </script>

  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoadOkay()" onerror="gapiLoadFail(event)"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoadOkay()" onerror="gisLoadFail(event)"></script>

</body>
</html>

GAPI コールバック

この例では、 トークンモデルを作成し、gapi.auth2 モジュールを削除し、 JavaScript の Google API クライアント ライブラリ

変数は、ライブラリの読み込み順序を指定するために使用されます。GAPI 呼び出しが 有効なアクセス トークンが返された後、コールバック内からこの関数を呼び出します。

ページを最初に開いたときにユーザーは [カレンダーを表示] ボタンを押すことが求められます。 カレンダー情報を更新したいときに再び設定されます。

<!DOCTYPE html>
<html>
<head>
  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
  <h1>GAPI with GIS callbacks</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
  <script>
    let tokenClient;
    let gapiInited;
    let gisInited;

    document.getElementById("showEventsBtn").style.visibility="hidden";
    document.getElementById("revokeBtn").style.visibility="hidden";

    function checkBeforeStart() {
       if (gapiInited && gisInited){
          // Start only when both gapi and gis are initialized.
          document.getElementById("showEventsBtn").style.visibility="visible";
          document.getElementById("revokeBtn").style.visibility="visible";
       }
    }

    function gapiInit() {
      gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
        gapiInited = true;
        checkBeforeStart();
      });
    }

    function gapiLoad() {
        gapi.load('client', gapiInit)
    }

    function gisInit() {
     tokenClient = google.accounts.oauth2.initTokenClient({
                client_id: 'YOUR_CLIENT_ID',
                scope: 'https://www.googleapis.com/auth/calendar.readonly',
                callback: '',  // defined at request time
            });
      gisInited = true;
      checkBeforeStart();
    }

    function showEvents() {

      tokenClient.callback = (resp) => {
        if (resp.error !== undefined) {
          throw(resp);
        }
        // GIS has automatically updated gapi.client with the newly issued access token.
        console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));

        gapi.client.calendar.events.list({ 'calendarId': 'primary' })
        .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
        .catch(err => console.log(err));

        document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
      }

      // Conditionally ask users to select the Google Account they'd like to use,
      // and explicitly obtain their consent to fetch their Calendar.
      // NOTE: To request an access token a user gesture is necessary.
      if (gapi.client.getToken() === null) {
        // Prompt the user to select a Google Account and asked for consent to share their data
        // when establishing a new session.
        tokenClient.requestAccessToken({prompt: 'consent'});
      } else {
        // Skip display of account chooser and consent dialog for an existing session.
        tokenClient.requestAccessToken({prompt: ''});
      }
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
        document.getElementById("showEventsBtn").innerText = "Show Calendar";
      }
    }
  </script>
</body>
</html>

認可コードフローの例

Google Identity Service ライブラリのポップアップ UX では、URL リダイレクトを使用して、 認証コードをバックエンド トークン エンドポイントに直接返す。または、 ユーザーのブラウザで実行される JavaScript コールバック ハンドラで、 レスポンスを返すのが難しくなりますいずれの場合も、バックエンド プラットフォームは OAuth 2.0 フローを実行して有効な更新トークンとアクセス トークンを取得します。

従来の方法

サーバーサイド ウェブアプリ

バックエンド プラットフォームで動作するサーバーサイド アプリ用の Google ログイン ユーザーの同意を得るために Google へのリダイレクトを使用する。

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>
    <script>
      function start() {
        gapi.load('auth2', function() {
          auth2 = gapi.auth2.init({
            client_id: 'YOUR_CLIENT_ID',
            api_key: 'YOUR_API_KEY',
            discovery_docs: ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
            // Scopes to request in addition to 'profile' and 'email'
            scope: 'https://www.googleapis.com/auth/cloud-translation',
          });
        });
      }
      function signInCallback(authResult) {
        if (authResult['code']) {
          console.log("sending AJAX request");
          // Send authorization code obtained from Google to backend platform
          $.ajax({
            type: 'POST',
            url: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
            // Always include an X-Requested-With header to protect against CSRF attacks.
            headers: {
              'X-Requested-With': 'XMLHttpRequest'
            },
            contentType: 'application/octet-stream; charset=utf-8',
            success: function(result) {
              console.log(result);
            },
            processData: false,
            data: authResult['code']
          });
        } else {
          console.log('error: failed to obtain authorization code')
        }
      }
    </script>
  </head>
  <body>
    <button id="signinButton">Sign In With Google</button>
    <script>
      $('#signinButton').click(function() {
        // Obtain an authorization code from Google
        auth2.grantOfflineAccess().then(signInCallback);
      });
    </script>
  </body>
</html>

リダイレクトを使用した HTTP/REST

ウェブサーバー アプリケーション用 OAuth 2.0 の使用による認証コードの送信 バックエンドプラットフォームに ルーティングされますユーザーの同意の処理方法 ユーザーのブラウザを Google にリダイレクトします。

/\*
 \* 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 &lt;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_AUTHORIZATION_CODE_ENDPOINT_URL',
                '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();
}

新しい方法

GIS ポップアップ UX

この例は、Google Identity Service の JavaScript ライブラリのみを示しています。 認証コードモデルを使用して、ユーザーの同意と同意のためのポップアップ ダイアログ Google から認証コードを受け取るためのコールバック ハンドラ。内容 構成に必要な最小限の手順を示すために、 同意を取得してバックエンドに認証コードを送信する できます。

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly',
          ux_mode: 'popup',
          callback: (response) => {
            var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
            // Send auth code to your backend platform
            const xhr = new XMLHttpRequest();
            xhr.open('POST', code_receiver_uri, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onload = function() {
              console.log('Signed in as: ' + xhr.responseText);
            };
            xhr.send('code=' + response.code);
            // After receipt, the code is exchanged for an access token and
            // refresh token, and the platform then updates this web app
            // running in user's browser with the requested calendar info.
          },
        });
      }
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

GIS リダイレクトの UX

認可コードモデルは、UX モードのポップアップとリダイレクトをサポートしています。 プラットフォームでホストされるエンドポイントにユーザーごとの認証コードを送信する。 リダイレクトの UX モードは次のようになります。

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/photoslibrary.readonly',
          ux_mode: 'redirect',
          redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
        });
      }
      // Request an access token
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

JavaScript ライブラリ

Google Identity Services は、ユーザーの認証およびアクセスに使用する Google Cloud の機能を 1 つに統合して置き換え、 複数の異なるライブラリやモジュールに

Identity Services に移行する際に必要なアクション:

既存の JS ライブラリ 新しい JS ライブラリ メモ
apis.google.com/js/api.js accounts.google.com/gsi/client 新しいライブラリを追加し、暗黙的フローに従います。
apis.google.com/js/client.js accounts.google.com/gsi/client 新しいライブラリと認証コードフローを追加します。

ライブラリ クイック リファレンス

以前の Google ログイン JavaScript のオブジェクトとメソッドの比較 クライアント ライブラリと新しい Google Identity Services ライブラリと、 注意事項 - 追加情報と移行中の対応。

新規 メモ
GoogleAuth オブジェクトおよび関連するメソッド:
GoogleAuth.attachClickHandler() 削除
GoogleAuth.currentUser.get() 削除
GoogleAuth.currentUser.listen() 削除
GoogleAuth.disconnect() google.accounts.oauth2.revoke 古いデータを新しいものに差し替えます。取り消しは https://myaccount.google.com/permissions からも行われる場合があります。
GoogleAuth.grantOfflineAccess() 削除し、認可コードフローに沿って対応します。
GoogleAuth.isSignedIn.get() 削除
GoogleAuth.isSignedIn.listen() 削除
GoogleAuth.signIn() 削除
GoogleAuth.signOut() 削除
GoogleAuth.then() 削除
GoogleUser オブジェクトと関連するメソッド:
GoogleUser.disconnect() google.accounts.id.revoke 古いデータを新しいものに差し替えます。取り消しは https://myaccount.google.com/permissions からも行われる場合があります。
GoogleUser.getAuthResponse() requestCode() or requestAccessToken() 古いものを新しいものに置換
GoogleUser.getBasicProfile() 削除代わりに ID トークンを使用してください。Google ログインからの移行をご覧ください。
GoogleUser.getGrantedScopes() hasGrantedAnyScope() 古いものを新しいものに置換
GoogleUser.getHostedDomain() 削除
GoogleUser.getId() 削除
GoogleUser.grantOfflineAccess() 削除し、認可コードフローに沿って対応します。
GoogleUser.grant() 削除
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() 古いものを新しいものに置換
GoogleUser.isSignedIn() 削除
GoogleUser.reloadAuthResponse() requestAccessToken() 古いものを削除し、new を呼び出して期限切れまたは取り消し済みのアクセス トークンを置き換えます。
gapi.auth2 オブジェクトと関連するメソッドの一覧を使用します。
gapi.auth2.AuthorizeConfig オブジェクト TokenClientConfig または CodeClientConfig 古いものを新しいものに置換
gapi.auth2.AuthorizeResponse オブジェクト 削除
gapi.auth2.AuthResponse オブジェクト 削除
gapi.auth2.authorize() requestCode() or requestAccessToken() 古いものを新しいものに置換
gapi.auth2.ClientConfig() TokenClientConfig または CodeClientConfig 古いものを新しいものに置換
gapi.auth2.getAuthInstance() 削除
gapi.auth2.init() initTokenClient() or initCodeClient() 古いものを新しいものに置換
gapi.auth2.OfflineAccessOptions オブジェクト 削除
gapi.auth2.SignInOptions オブジェクト 削除
gapi.signin2 オブジェクトおよび関連メソッド:
gapi.signin2.render() 削除HTML DOM の読み込み g_id_signin 要素または JS 呼び出しで google.accounts.id.renderButton ユーザーの Google アカウントへのログインをトリガーする。

認証情報の例

既存の認証情報

Google ログイン プラットフォーム ライブラリGoogle API クライアント ライブラリ JavaScript、または Google Auth 2.0 エンドポイントへの直接呼び出しは、 OAuth 2.0 アクセス トークンと OpenID Connect ID トークンの両方を 1 つの レスポンスが返されます。

access_tokenid_token の両方を含むレスポンスの例:

  {
    "token_type": "Bearer",
    "access_token": "ya29.A0ARrdaM-SmArZaCIh68qXsZSzyeU-8mxhQERHrP2EXtxpUuZ-3oW8IW7a6D2J6lRnZrRj8S6-ZcIl5XVEqnqxq5fuMeDDH_6MZgQ5dgP7moY-yTiKR5kdPm-LkuPM-mOtUsylWPd1wpRmvw_AGOZ1UUCa6UD5Hg",
    "scope": "https://www.googleapis.com/auth/calendar.readonly",
    "login_hint": "AJDLj6I2d1RH77cgpe__DdEree1zxHjZJr4Q7yOisoumTZUmo5W2ZmVFHyAomUYzLkrluG-hqt4RnNxrPhArd5y6p8kzO0t8xIfMAe6yhztt6v2E-_Bb4Ec3GLFKikHSXNh5bI-gPrsI",
    "expires_in": 3599,
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzI2NDMxNjUxOTQzNjk4NjAwIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IkJBSW55TjN2MS1ZejNLQnJUMVo0ckEiLCJuYW1lIjoiQnJpYW4gRGF1Z2hlcnR5IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdnenAyTXNGRGZvbVdMX3VDemRYUWNzeVM3ZGtxTE5ybk90S0QzVXNRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkJyaWFuIiwiZmFtaWx5X25hbWUiOiJEYXVnaGVydHkiLCJsb2NhbGUiOiJlbiIsImlhdCI6MTYzODk5MTYzOCwiZXhwIjoxNjM4OTk1MjM4LCJqdGkiOiI5YmRkZjE1YWFiNzE2ZDhjYmJmNDYwMmM1YWM3YzViN2VhMDQ5OTA5In0.K3EA-3Adw5HA7O8nJVCsX1HmGWxWzYk3P7ViVBb4H4BoT2-HIgxKlx1mi6jSxIUJGEekjw9MC-nL1B9Asgv1vXTMgoGaNna0UoEHYitySI23E5jaMkExkTSLtxI-ih2tJrA2ggfA9Ekj-JFiMc6MuJnwcfBTlsYWRcZOYVw3QpdTZ_VYfhUu-yERAElZCjaAyEXLtVQegRe-ymScra3r9S92TA33ylMb3WDTlfmDpWL0CDdDzby2asXYpl6GQ7SdSj64s49Yw6mdGELZn5WoJqG7Zr2KwIGXJuSxEo-wGbzxNK-mKAiABcFpYP4KHPEUgYyz3n9Vqn2Tfrgp-g65BQ",
    "session_state": {
      "extraQueryParams": {
        "authuser": "0"
      }
    },
    "first_issued_at": 1638991637982,
    "expires_at": 1638995236982,
    "idpId": "google"
  }

Google Identity Services の認証情報

Google Identity Services ライブラリは、次の内容を返します。

  • 認可に使用する場合はアクセス トークン、

    {
      "access_token": "ya29.A0ARrdaM_LWSO-uckLj7IJVNSfnUityT0Xj-UCCrGxFQdxmLiWuAosnAKMVQ2Z0LLqeZdeJii3TgULp6hR_PJxnInBOl8UoUwWoqsrGQ7-swxgy97E8_hnzfhrOWyQBmH6zs0_sUCzwzhEr_FAVqf92sZZHphr0g",
      "token_type": "Bearer",
      "expires_in": 3599,
      "scope": "https://www.googleapis.com/auth/calendar.readonly"
    }
    
  • 認証に使用する場合は ID トークンを使用します。

    {
      "clientId": "538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com",
      "credential": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxODkyZWI0OWQ3ZWY5YWRmOGIyZTE0YzA1Y2EwZDAzMjcxNGEyMzciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzkxNTcyNjQsImF1ZCI6IjUzODM0NDY1MzI1NS03NThjNWg1aXNjNDV2Z2syN2Q4aDhkZWFib3ZwZzZ0by5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzcyNjQzMTY1MTk0MzY5ODYwMCIsIm5vbmNlIjoiZm9vYmFyIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkJyaWFuIERhdWdoZXJ0eSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ3pwMk1zRkRmb21XTF91Q3pkWFFjc3lTN2RrcUxOcm5PdEtEM1VzUT1zOTYtYyIsImdpdmVuX25hbWUiOiJCcmlhbiIsImZhbWlseV9uYW1lIjoiRGF1Z2hlcnR5IiwiaWF0IjoxNjM5MTU3NTY0LCJleHAiOjE2MzkxNjExNjQsImp0aSI6IjRiOTVkYjAyZjU4NDczMmUxZGJkOTY2NWJiMWYzY2VhYzgyMmI0NjUifQ.Cr-AgMsLFeLurnqyGpw0hSomjOCU4S3cU669Hyi4VsbqnAV11zc_z73o6ahe9Nqc26kPVCNRGSqYrDZPfRyTnV6g1PIgc4Zvl-JBuy6O9HhClAK1HhMwh1FpgeYwXqrng1tifmuotuLQnZAiQJM73Gl-J_6s86Buo_1AIx5YAKCucYDUYYdXBIHLxrbALsA5W6pZCqqkMbqpTWteix-G5Q5T8LNsfqIu_uMBUGceqZWFJALhS9ieaDqoxhIqpx_89QAr1YlGu_UO6R6FYl0wDT-nzjyeF5tonSs3FHN0iNIiR3AMOHZu7KUwZaUdHg4eYkU-sQ01QNY_11keHROCRQ",
      "select_by": "user"
    }
    

無効なトークンのレスポンス

を使用して API リクエストを送信しようとした場合の Google からのレスポンスの例 アクセス トークンが期限切れ、取り消された、無効である場合:

HTTP レスポンス ヘッダー

  www-authenticate: Bearer realm="https://accounts.google.com/", error="invalid_token"

レスポンスの本文

  {
    "error": {
      "code": 401,
      "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
      "errors": [
        {
          "message": "Invalid Credentials",
          "domain": "global",
          "reason": "authError",
          "location": "Authorization",
          "locationType": "header"
        }
      ],
      "status": "UNAUTHENTICATED"
    }
  }