Migrar para os Serviços de Identificação do Google

Visão geral

Para obter um token de acesso por usuário para chamar as APIs do Google, o Google oferece vários Bibliotecas JavaScript:

Este guia fornece instruções para migrar dessas bibliotecas para a API biblioteca Identity Services.

Ao seguir este guia, você vai:

  • Substitua a biblioteca do Platform, que foi descontinuada, pela biblioteca Identity Services. e
  • Se você estiver usando a biblioteca de cliente da API, remova o módulo descontinuado gapi.auth2. e objetos, substituindo-os pelos equivalentes dos Serviços de Identificação.

Para uma descrição do que mudou com o JavaScript dos Serviços de Identificação leia a visão geral e como funciona a autorização de usuários para analisar os principais termos e conceitos.

Se você estiver procurando a autenticação para inscrição e login de usuários, consulte Migrar do Login do Google.

Identificar seu fluxo de autorização

Há dois fluxos de autorização de usuário possíveis: implícito e de autorização o código-fonte é alterado.

Analise seu app da Web para identificar o tipo de fluxo de autorização atual que está sendo usado.

Indicações de que seu app da Web está usando o fluxo implícito:

Indicações de que seu app da Web está usando o fluxo do código de autorização:

  • A implementação é feita com base nestes fatores:

  • O app é executado no navegador do usuário e na plataforma de back-end.

  • Sua plataforma de back-end hospeda um endpoint de código de autorização.

  • Sua plataforma de back-end chama APIs do Google em nome dos usuários sem exigir a presença deles, ou seja, modo off-line.

  • Os tokens de atualização são gerenciados e armazenados pela plataforma de back-end.

Em alguns casos, sua base de código pode oferecer suporte aos dois fluxos.

Escolher um fluxo de autorização

Antes de iniciar a migração, você precisa determinar se continua com o fluxo atual ou a adoção de um fluxo diferente melhor atende às suas necessidades.

Consulte Como escolher um fluxo de autorização para entender as principais diferenças e as vantagens e desvantagens dos dois fluxos.

Na maioria dos casos, o fluxo do código de autorização é recomendado, pois oferece a o mais alto nível de segurança do usuário. A implementação desse fluxo também permite a plataforma para adicionar novas funcionalidades off-line com mais facilidade, como a busca de atualizações para notificar os usuários sobre mudanças notáveis em suas agendas, fotos, inscrições e assim por diante.

Escolha um fluxo de autorização usando os seletores abaixo.

Fluxo implícito

Conseguir um token de acesso para uso no navegador enquanto o usuário estiver presente.

Os exemplos de fluxo implícito mostram apps da Web antes e depois da migração para Serviços de Identificação do Google.

Fluxo do código de autorização

Um código de autorização por usuário emitido pelo Google é enviado ao seu back-end em que os dados são trocados por um token de acesso e de atualização.

Os exemplos de fluxo do código de autorização mostram apps da Web antes e depois. migração para os Serviços de Identificação.

Ao longo deste guia, siga as instruções listadas em negrito para Adicionar, Remover, Atualizar ou Substituir funcionalidade existente.

Mudanças no seu app da Web no navegador

Esta seção analisa as alterações que você fará em seu aplicativo da Web no navegador quando migração para a biblioteca JavaScript dos Serviços de Identificação do Google.

identificação do código afetado e testes

Um cookie de depuração pode ajudar a localizar o código afetado e testar após a descontinuação do seu modelo.

Em apps grandes ou complexos, pode ser difícil encontrar todo o código afetado pelo descontinuação do módulo gapi.auth2. Para registrar o uso existente de funcionalidade descontinuada ao console, defina o valor do atributo G_AUTH2_MIGRATION para informational. Opcionalmente, adicione dois-pontos seguidos por um valor de chave para também registrar no armazenamento de sessão. Após o login recebimento das credenciais, revise ou envie os registros coletados a um back-end para uso posterior análise. Por exemplo, informational:showauth2use salva a origem e o URL em um chave de armazenamento de sessão chamada showauth2use.

Para verificar o comportamento do app quando o módulo gapi.auth2 não estiver mais carregado, defina o do cookie G_AUTH2_MIGRATION para enforced. Isso permite testar comportamento pós-suspensão antes da data de aplicação.

Possíveis valores de cookie G_AUTH2_MIGRATION:

  • enforced Não carregue o módulo gapi.auth2.
  • informational Registrar o uso de funcionalidade descontinuada no console JS. Registrar também para o armazenamento de sessão quando um nome de chave opcional for definido: informational:key-name:

Para minimizar o impacto no usuário, recomendamos que você defina o cookie localmente durante o desenvolvimento e teste, antes de usá-lo em ambientes de produção.

Bibliotecas e módulos

O módulo gapi.auth2 gerencia a autenticação do usuário para login e a fluxo para autorização, substitua este módulo de uso suspenso e seus objetos e com a biblioteca de Serviços de Identificação do Google.

Adicione a biblioteca de Serviços de Identificação ao seu app da Web, incluindo-a no documento:

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

Remova todas as instâncias de carregamento do módulo auth2 usando gapi.load('auth2', function).

A biblioteca de Serviços de Identificação do Google substitui o uso do módulo gapi.auth2. Você pode continuar com segurança usando o módulo gapi.client na API do Google biblioteca de cliente para JavaScript e aproveitar a criação automática de métodos JS chamáveis de um documento de descoberta, reunindo várias chamadas de API, e a funcionalidade de gerenciamento de CORS.

Cookies

A autorização do usuário não requer o uso de cookies.

Consulte Como migrar do Login do Google para mais detalhes sobre como a autenticação de usuários. faz uso de cookies, e Como o Google usa cookies para o uso de cookies por outros produtos e serviços do Google.

Credenciais

Os Serviços de Identificação do Google dividem a autenticação e a autorização do usuário em duas operações distintas, e as credenciais do usuário são separadas: o token de ID usado para identificam um usuário é retornado separadamente do token de acesso usado para autorização.

Para ver essas mudanças, consulte credenciais de exemplo.

Fluxo implícito

Separar a autenticação e a autorização do usuário removendo o perfil do usuário processamento dos fluxos de autorização.

Remova estas referências do cliente JavaScript do Login do Google:

Métodos

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

Fluxo do código de autorização

Os Serviços de Identificação dividem as credenciais no navegador em token de ID e acesso com base no token correto anterior. Essa mudança não se aplica a credenciais recebidas por canais diretos chamadas para endpoints OAuth 2.0 do Google da sua plataforma de back-end ou por meio de bibliotecas em execução em um servidor seguro em sua plataforma, como o Google Cliente Node.js de APIs.

Estado da sessão

Antes, o Login do Google ajudava você a gerenciar o status de login dos usuários usando:

Você é responsável por gerenciar o estado de login e as sessões de usuário na sua Web app.

Remova estas referências do cliente JavaScript do Login do Google:

Objetos:

  • gapi.auth2.SignInOptions

Métodos:

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

Configuração do cliente

Atualizar seu app da Web para inicializar um cliente de token para a autenticação implícita ou fluxo do código de autorização.

Remova estas referências do cliente JavaScript do Login do Google:

Objetos:

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

Métodos:

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

Fluxo implícito

Adicione um objeto TokenClientConfig e uma chamada initTokenClient() ao configure seu app da Web seguindo o exemplo em inicializar um token cliente.

Substitua as referências do cliente JavaScript do Login do Google por Google Serviços de Identificação:

Objetos:

  • gapi.auth2.AuthorizeConfig com TokenClientConfig

Métodos:

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

Parâmetros:

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

Fluxo do código de autorização

Adicione um objeto CodeClientConfig e uma chamada initCodeClient() para configurar. seu app da Web, seguindo o exemplo em inicializar um cliente de código.

Ao mudar do fluxo implícito para o código de autorização:

Remover referências do cliente JavaScript do Login do Google

Objetos:

  • gapi.auth2.AuthorizeConfig

Métodos:

  • gapi.auth2.init()

Parâmetros:

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

Solicitação de token

Um gesto do usuário, como um clique em um botão, gera uma solicitação que resulta em uma token de acesso do usuário retornado diretamente para o navegador do usuário com a ou para sua plataforma de back-end após trocar um código de autorização por usuário para obter um token de acesso e um token de atualização.

Fluxo implícito

Os tokens de acesso podem ser obtidos e usados no navegador enquanto o usuário está conectado e tem uma sessão ativa com o Google. No modo implícito, um usuário gesto é necessário para solicitar um token de acesso, mesmo se houver um solicitação.

Substitua as referências do cliente JavaScript do Login do Google por Google Serviços de Identificação:

Métodos:

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

Adicione um link ou botão para chamar requestAccessToken() e iniciar a fluxo de UX pop-up para solicitar um token de acesso ou para obter um novo token quando o token atual expirar.

Atualize sua base de código para:

  • Acione o fluxo de tokens OAuth 2.0 com requestAccessToken().
  • Oferecer suporte à autorização incremental usando requestAccessToken e OverridableTokenClientConfig para separar uma solicitação por muitos escopos. em várias solicitações menores.
  • Solicite um novo token quando o atual expirar ou for revogado.

Trabalhar com vários escopos pode exigir mudanças estruturais na sua base de código solicitar acesso a escopos somente quando necessário, e não todos de uma vez, isso é conhecido como autorização incremental. Cada solicitação deve conter o com poucos escopos e idealmente um único. Saiba como lidar com o de consentimento para saber mais sobre como atualizar seu app para autorização.

Quando um token de acesso expira, o módulo gapi.auth2 recebe automaticamente um novo token de acesso válido para seu aplicativo da Web. Para melhorar a segurança do usuário, o processo de atualização automática de tokens não é compatível com a plataforma de identidade Biblioteca de serviços. Seu app da Web precisa ser atualizado para detectar um acesso expirado e solicitar um novo. Consulte a seção "Tratamento de tokens" abaixo para saber mais.

Fluxo do código de autorização

Adicione um link ou botão para chamar requestCode() e solicitar uma autorização. códigos do Google. Para ver um exemplo, consulte Acionar fluxo de código OAuth 2.0.

Consulte a seção "Tratamento de tokens" abaixo para saber mais sobre como responder a uma token de acesso expirado ou revogado.

Processamento de tokens

Adicionar tratamento de erros para detectar chamadas de API do Google com falha quando uma solicitação token de acesso revogado é usado e para solicitar um novo token de acesso válido.

Um código de status HTTP da mensagem de erro 401 Unauthorized e invalid_token é retornados pelas APIs do Google quando um token de acesso expirado ou revogado é usado. Para um exemplo, consulte Resposta de token inválido.

Tokens expirados

Os tokens de acesso são de curta duração e geralmente válidos apenas por alguns minutos.

Revogação de token

O proprietário de uma Conta do Google pode revogar o consentimento dado anteriormente a qualquer momento. Fazer então invalida os tokens de acesso e de atualização atuais. A revogação pode ser acionada a partir da sua plataforma usando revoke() ou por meio de uma do Google.

Substitua as referências do cliente JavaScript do Login do Google por Google Serviços de Identificação:

Métodos:

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

Chame revoke quando um usuário excluir a conta na sua plataforma, ou deseja remover o consentimento para compartilhar dados com seu app.

O Google mostra uma caixa de diálogo de consentimento ao usuário quando o app da Web ou o back-end plataforma solicita um token de acesso. Confira exemplos de caixas de diálogo de consentimento pelo Google aos usuários.

Antes de emitir um token de acesso para seu app, é necessário ter uma conta do Google sessão é necessária para solicitar o consentimento do usuário e registrar o resultado. O usuário pode ser necessário fazer login em uma Conta do Google se uma sessão existente não tiver sido já estabelecidos.

Login do usuário

Os usuários podem estar conectados a uma Conta do Google em uma guia separada do navegador ou de forma nativa em um navegador ou sistema operacional. Recomendamos adicionar a opção Fazer login com Google ao seu site para estabelecer uma sessão ativa entre uma Conta do Google. e o navegador quando o usuário abre o app pela primeira vez. Com isso, esses Benefícios:

  • Minimiza o número de vezes que um usuário precisa fazer login para solicitar acesso token inicia o processo de login na Conta do Google se uma sessão ativa não ainda não existem.
  • Use diretamente o campo credential email do token de ID do JWT como o valor do o parâmetro login_hint em CodeClientConfig ou TokenClientConfig objetos. Isso é especialmente útil se sua plataforma não tiver um de gerenciamento de contas de usuário.
  • Pesquise e associe uma Conta do Google a uma conta de usuário local existente no sua plataforma, ajudando a minimizar contas duplicadas nela.
  • Quando uma nova conta local é criada, suas caixas de diálogo e fluxo de inscrição podem ser claramente separados das caixas de diálogo e fluxos de autenticação do usuário, reduzindo a o número de etapas necessárias e melhorar a taxa de desistência.

Após o login e antes da emissão de um token de acesso, os usuários precisam consentir do seu aplicativo para os escopos solicitados.

Após o consentimento, um token de acesso é retornado com uma lista de escopos aprovados ou rejeitados pelo usuário.

Com as permissões granulares, os usuários podem aprovar ou negar escopos individuais. Quando solicitar acesso a vários escopos, cada um deles será concedido ou rejeitado independentes dos outros escopos. Com base na escolha do usuário do seu app ativa recursos e funcionalidades que dependem de um escopo individual.

Fluxo implícito

Substitua as referências do cliente JavaScript do Login do Google por Google Serviços de Identificação:

Objetos:

  • gapi.auth2.AuthorizeResponse com TokenClient.TokenResponse
  • gapi.auth2.AuthResponse com TokenClient.TokenResponse

Métodos:

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

Remova referências do cliente JavaScript do Login do Google:

Métodos:

  • GoogleUser.getAuthResponse()

Atualize seu app da Web com hasGrantedAllScopes() e hasGrantedAnyScope() seguindo este exemplo de permissões granulares.

Fluxo do código de autorização

Atualizar ou Adicionar um endpoint do código de autorização ao back-end plataforma seguindo as instruções em Processamento de código de autenticação.

Atualize sua plataforma para seguir as etapas descritas na seção Usar código Model para validar a solicitação, receber um token de acesso e atualizar com base no token correto anterior.

Atualizar sua plataforma para ativar ou desativar seletivamente os recursos e funcionalidades com base nos escopos individuais aprovados pelo usuário seguir as instruções para autorização incremental e examinar escopos de acesso concedidos pelo usuário.

Exemplos de fluxo implícito

Como era antes

Biblioteca de cliente GAPI

Exemplo da biblioteca de cliente das APIs do Google para JavaScript executado no navegador usando uma caixa de diálogo pop-up para o consentimento do usuário.

O módulo gapi.auth2 é carregado e usado automaticamente gapi.client.init(), portanto, está oculto.

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

Biblioteca de cliente JS

OAuth 2.0 para aplicativos da Web do lado do cliente em execução no navegador usando uma caixa de diálogo pop-up para o consentimento do usuário.

O módulo gapi.auth2 é carregado manualmente.

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

Endpoints do OAuth 2.0

OAuth 2.0 para aplicativos da Web do lado do cliente em execução no navegador usando redireciona para o Google para obter o consentimento do usuário.

Este exemplo mostra chamadas diretas para os endpoints OAuth 2.0 do Google a partir do navegador do usuário e não usa o módulo gapi.auth2 ou um JavaScript biblioteca.

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

Como será agora

Somente SIG

Este exemplo mostra apenas a biblioteca JavaScript do Google Identity Service usando o modelo de token e a caixa de diálogo pop-up de consentimento do usuário. É fornecido para ilustrar o número mínimo de etapas necessárias para configurar um cliente, solicitar e obter um token de acesso e chamar uma API do Google.

<!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 de sincronização/await

Este exemplo mostra como adicionar a biblioteca do Google Identity Service usando o modelo de token, remova o módulo gapi.auth2 e chame uma API usando a Biblioteca de cliente das APIs do Google para JavaScript.

Commits, async e await são usados para aplicar a ordem de carregamento da biblioteca e para detectar e repetir erros de autorização. Uma chamada de API é feita somente após um endereço está disponível.

Os usuários devem pressionar o botão "Mostrar agenda" quando o token de acesso ausente quando a página é carregada pela primeira vez ou depois que o token de acesso expirou.

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

Callback GAPI

Este exemplo mostra como adicionar a biblioteca do Google Identity Service usando o modelo de token, remova o módulo gapi.auth2 e chame uma API usando a Biblioteca de cliente das APIs do Google para JavaScript.

As variáveis são usadas para impor a ordem de carregamento da biblioteca. As chamadas GAPI são feitas dentro do retorno de chamada após o retorno de um token de acesso válido.

Os usuários devem pressionar o botão "Mostrar agenda" na primeira vez que a página for acessada carregado e novamente quando quiserem atualizar as informações da Agenda.

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

Exemplos de fluxo do código de autorização

A UX pop-up da biblioteca do Google Identity Service pode usar um redirecionamento de URL para retornar um código de autorização diretamente para o endpoint do token de back-end ou um Manipulador de callback JavaScript em execução no navegador do usuário que atua como proxy do resposta à sua plataforma. Em ambos os casos, a plataforma de back-end completa o fluxo OAuth 2.0 para obter um token válido de atualização e acesso.

Como era antes

Apps da Web do lado do servidor

Login do Google para apps do lado do servidor em execução na plataforma de back-end usando um redirecionamento para o Google para obter o consentimento do usuário.

<!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 usando redirecionamento

Usar o OAuth 2.0 para aplicativos de servidor da Web para enviar código de autorização do navegador do usuário para a plataforma de back-end. Consentimento do usuário processado por redirecionando o navegador do usuário para o 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();
}

Como será agora

UX em pop-up de SIG

Este exemplo mostra apenas a biblioteca JavaScript do Google Identity Service usando o modelo de código de autorização, uma caixa de diálogo pop-up para o consentimento do usuário e gerenciador de callback para receber o código de autorização do Google. É fornecido para ilustrar o número mínimo de etapas necessárias para configurar um cliente, consiga o consentimento e envie um código de autorização ao back-end de plataforma.

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

UX de redirecionamento de SIG

O modelo do código de autorização é compatível com os modos pop-up e de redirecionamento de UX para enviar um código de autorização por usuário para o endpoint hospedado pela sua plataforma. O modo de UX de redirecionamento é mostrado aqui:

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

Bibliotecas JavaScript

Os Serviços de Identificação do Google são uma única biblioteca JavaScript usada para e autorização que consolida e substitui recursos e funcionalidade encontrada em diversas bibliotecas e módulos:

Ações a serem tomadas ao migrar para os Serviços de Identificação:

Biblioteca JS existente Nova biblioteca JS Observações
apis.google.com/js/api.js accounts.google.com/gsi/client Adicionar uma nova biblioteca e seguir o fluxo implícito.
apis.google.com/js/client.js accounts.google.com/gsi/client Adicione uma nova biblioteca e o fluxo do código de autorização.

Referência rápida de biblioteca

Comparação de objetos e métodos entre o antigo JavaScript do Login do Google de cliente, a biblioteca dos novos Serviços de Identificação do Google e Observações com mais informações e ações a serem tomadas durante a migração.

Antigo Novo Observações
GoogleAuth e métodos associados:
GoogleAuth.attachClickHandler() Remover
GoogleAuth.currentUser.get() Remover
GoogleAuth.currentUser.listen() Remover
GoogleAuth.disconnect() google.accounts.oauth2.revoke Substituir antigo por novo. A revogação também pode ocorrer em https://myaccount.google.com/permissions
GoogleAuth.grantOfflineAccess() Remova-o. Siga o fluxo do código de autorização.
GoogleAuth.isSignedIn.get() Remover
GoogleAuth.isSignedIn.listen() Remover
GoogleAuth.signIn() Remover
GoogleAuth.signOut() Remover
GoogleAuth.then() Remover
GoogleUser e métodos associados:
GoogleUser.disconnect() google.accounts.id.revoke Substituir antigo por novo. A revogação também pode ocorrer em https://myaccount.google.com/permissions
GoogleUser.getAuthResponse() requestCode() or requestAccessToken() Substituir antigo por novo
GoogleUser.getBasicProfile() Remover. Use o token de ID em Migrar do Login do Google.
GoogleUser.getGrantedScopes() hasGrantedAnyScope() Substituir antigo por novo
GoogleUser.getHostedDomain() Remover
GoogleUser.getId() Remover
GoogleUser.grantOfflineAccess() Remova-o. Siga o fluxo do código de autorização.
GoogleUser.grant() Remover
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() Substituir antigo por novo
GoogleUser.isSignedIn() Remover
GoogleUser.reloadAuthResponse() requestAccessToken() Remova o antigo e chame o novo para substituir o token de acesso expirado ou revogado.
objeto gapi.auth2 e métodos associados:
Objeto gapi.auth2.AuthorizeConfig TokenClientConfig ou CodeClientConfig Substituir antigo por novo
Objeto gapi.auth2.AuthorizeResponse Remover
Objeto gapi.auth2.AuthResponse Remover
gapi.auth2.authorize() requestCode() or requestAccessToken() Substituir antigo por novo
gapi.auth2.ClientConfig() TokenClientConfig ou CodeClientConfig Substituir antigo por novo
gapi.auth2.getAuthInstance() Remover
gapi.auth2.init() initTokenClient() or initCodeClient() Substituir antigo por novo
Objeto gapi.auth2.Off-lineAccessOptions Remover
Objeto gapi.auth2.SignInOptions Remover
objeto gapi.signin2 e métodos associados:
gapi.signin2.render() Remover. O carregamento do DOM HTML da g_id_signin ou uma chamada de JS para google.accounts.id.renderButton aciona o login do usuário em uma Conta do Google.

Exemplo de credenciais

Credenciais atuais

A biblioteca da plataforma de Login do Google, a biblioteca de cliente da API do Google para JavaScript ou chamadas diretas para endpoints do Google Auth 2.0 retornam um token de acesso OAuth 2.0 e um token de ID do OpenID Connect em um único resposta.

Exemplo de resposta contendo access_token e id_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"
  }

Credencial dos Serviços de Identificação do Google

A biblioteca de Serviços de Identificação do Google retorna:

  • um token de acesso quando usado para autorização:

    {
      "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"
    }
    
  • ou um token de ID para autenticação:

    {
      "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"
    }
    

Resposta de token inválida

Exemplo de resposta do Google ao tentar fazer uma solicitação de API usando uma token de acesso expirado, revogado ou inválido:

Cabeçalhos de resposta HTTP

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

Corpo da resposta

  {
    "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"
    }
  }