Visão geral
Para receber um token de acesso por usuário e chamar as APIs do Google, oferecemos várias bibliotecas JavaScript:
Este guia fornece instruções para migrar dessas bibliotecas para a biblioteca de serviços de identidade do Google.
Ao seguir este guia, você aprenderá a fazer o seguinte:
- substituir a Biblioteca da Plataforma suspensa pela biblioteca do Identity Services.
- Se estiver usando a biblioteca de cliente da API, remova o módulo
gapi.auth2
obsoleto, os métodos e objetos dele, substituindo-os pelos equivalentes do Identity Services.
Para uma descrição do que mudou com a biblioteca JavaScript dos serviços de identidade, leia a visão geral e como funciona a autorização do usuário para analisar os principais termos e conceitos.
Se você estiver procurando a autenticação para o login e o login do usuário, consulte Migração do Login do Google.
Identifique seu fluxo de autorização
Há dois fluxos possíveis de autorização do usuário: código implícito e autorização.
Revise seu app da Web para identificar o tipo de fluxo de autorização que está sendo usado no momento.
indicações do seu app da Web que está usando o fluxo implícito:
- Seu app da Web é baseado apenas no navegador, sem plataforma de back-end.
- O usuário precisa estar presente para chamar as APIs do Google, seu app usa somente tokens de acesso e não requer tokens de atualização.
- Seu app da Web carrega
apis.google.com/js/api.js
. - A implementação é baseada no OAuth 2.0 para aplicativos da Web do lado do cliente.
- O app usa os módulos
gapi.client
ougapi.auth2
encontrados na biblioteca de cliente da API do Google para JavaScript.
Indicações do app da Web que usam o fluxo de código de autorização:
Sua implementação é baseada em:
O aplicativo é 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.
A plataforma de back-end chama as APIs do Google em nome dos usuários sem que eles estejam presentes, também conhecido como 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 ser compatível com os dois fluxos.
Escolher um fluxo de autorização
Antes de iniciar a migração, você precisa determinar se continuar com o fluxo atual ou adotar um fluxo diferente atende melhor às suas necessidades.
Veja como escolher um fluxo de autorização para entender as principais diferenças e compensações entre os dois fluxos.
Na maioria dos casos, o fluxo do código de autorização é recomendado, porque oferece o nível mais alto de segurança do usuário. A implementação desse fluxo também permite que sua plataforma adicione novas funcionalidades off-line com mais facilidade, como buscar atualizações para notificar os usuários sobre mudanças importantes na agenda, nas fotos, nas assinaturas e assim por diante.
Escolha um fluxo de autorização usando os seletores abaixo.
Fluxo implícito
Receber 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 o Identity Services.
Fluxo do código de autorização
Um código de autorização por usuário emitido pelo Google é entregue à sua plataforma de back-end, onde ele é trocado por um token de acesso e um token de atualização.
Os exemplos de fluxo de código de autorização mostram apps da Web antes e depois da migração para o Identity Services.
Neste guia, siga as instruções em negrito para Adicionar, Remover, Atualizar ou Substituir a funcionalidade existente.
Mudanças no app da Web no navegador
Esta seção analisa as alterações que você fará no app da Web no navegador ao migrar para a biblioteca JavaScript do Google Identity Services.
Como identificar códigos e testes afetados
Um cookie de depuração pode ajudar a localizar o código afetado e testar o comportamento após a suspensão de uso.
Em apps grandes ou complexos, pode ser difícil encontrar todo o código afetado pela
suspensão do módulo gapi.auth2
. Para registrar o uso atual de funcionalidade a ser suspensa no console, defina o valor do cookie G_AUTH2_MIGRATION
como informational
. Opcionalmente, adicione dois pontos seguidos por um valor de chave para registrar também o armazenamento da sessão.
Depois de fazer login e receber as credenciais, revise ou envie os registros coletados para um back-end para análise posterior. Por exemplo, informational:showauth2use
salva
a origem e o URL em uma chave de armazenamento de sessão chamada showauth2use
.
Para verificar o comportamento do app quando o módulo gapi.auth2
não for mais carregado,
defina o valor do cookie G_AUTH2_MIGRATION
como enforced
. Isso permite testar o comportamento pós-suspensão antes da data de aplicação.
Valores possíveis de cookies de G_AUTH2_MIGRATION
:
enforced
Não carregue o módulogapi.auth2
.informational
Registre o uso de recursos obsoletos no Console JS. Registre também no armazenamento da sessão quando um nome de chave opcional for definido:informational:key-name
.
Para minimizar o impacto ao usuário, recomendamos que você defina esse cookie localmente durante o desenvolvimento e o 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 o
fluxo implícito para autorização, substitui este módulo obsoleto e os
objetos e métodos dele pela biblioteca do Google Identity Services.
Adicione a biblioteca do Identity Services ao seu app da Web incluindo-a no documento:
<script src="https://accounts.google.com/gsi/client" async defer></script>
Remova qualquer instância do carregamento do módulo auth2
usando gapi.load('auth2', function)
.
A biblioteca de serviços de identidade do Google substitui o uso do módulo gapi.auth2
.
Você pode continuar usando o módulo gapi.client
na Biblioteca de cliente da API Google para JavaScript e aproveitar a criação automática de métodos JS chamáveis de um documento de descoberta, agrupamento em lote de várias chamadas de API e 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 ver detalhes sobre como a autenticação do usuário utiliza cookies e Como o Google usa cookies para o uso de cookies de outros produtos e serviços do Google.
Credenciais
O Google Identity Services separa a autenticação e a autorização de usuários em duas operações distintas, e as credenciais de usuários são separadas: o token de ID usado para identificar um usuário é retornado separadamente do token de acesso usado para autorização.
Para ver essas alterações, consulte os exemplos de credenciais.
Fluxo implícito
Separe a autenticação e a autorização de usuários removendo o gerenciamento de perfis de usuários dos fluxos de autorização.
Remova estas referências de clientes de JavaScript do Login do Google:
Métodos
GoogleUser.getBasicProfile()
GoogleUser.getId()
Fluxo do código de autorização
O Identity Services separa as credenciais no navegador nos tokens de código e acesso. Essa alteração não se aplica a credenciais recebidas por meio de chamadas diretas para endpoints do Google OAuth 2.0 da plataforma de back-end ou por bibliotecas em execução em um servidor seguro na plataforma, como o Cliente de APIs Node.js do Google.
Estado da sessão
Antes, o Login do Google ajudava você a gerenciar o status de login do usuário usando:
- Gerenciadores de callback para monitorar o estado da sessão do usuário.
- Listeners para eventos e alterações no status conectado de uma Conta do Google do usuário.
Você é responsável por gerenciar o estado de login e as sessões do usuário no seu app da Web.
Remova estas referências de clientes de 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
Atualize seu app da Web para inicializar um cliente de token para o fluxo de código de autorização ou implícito.
Remova estas referências de clientes de 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()
para
configurar seu app da Web, seguindo o exemplo em
inicializar um cliente de token.
Substitua referências de clientes JavaScript do Login do Google pelos Serviços de identidade do Google:
Objetos:
gapi.auth2.AuthorizeConfig
comTokenClientConfig
Métodos:
gapi.auth2.init()
comgoogle.accounts.oauth2.initTokenClient()
Parâmetros:
gapi.auth2.AuthorizeConfig.login_hint
comTokenClientConfig.hint
.gapi.auth2.GoogleUser.getHostedDomain()
comTokenClientConfig.hosted_domain
.
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 de código implícito para o 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 de botão, gera uma solicitação que resulta em um token de acesso retornado diretamente para o navegador do usuário com o fluxo implícito ou para sua plataforma de back-end após a troca de um código de autorização por usuário para um token de acesso e de atualização.
Fluxo implícito
Os tokens de acesso podem ser recebidos e usados no navegador enquanto o usuário está conectado e tem uma sessão ativa com o Google. No modo implícito, um gesto do usuário é necessário para solicitar um token de acesso, mesmo que haja uma solicitação anterior.
Substitua referências de clientes JavaScript do Login do Google: por Serviços de identidade do Google:
Métodos:
gapi.auth2.authorize()
comTokenClient.requestAccessToken()
GoogleUser.reloadAuthResponse()
comTokenClient.requestAccessToken()
Adicione um link ou botão para chamar requestAccessToken()
para iniciar o
fluxo de UX de pop-up para solicitar um token de acesso ou para receber um novo token quando o
token existente expirar.
Atualize sua base de código para o seguinte:
- Acione o fluxo de token do OAuth 2.0
com
requestAccessToken()
. - Ofereça compatibilidade com autorização incremental usando
requestAccessToken
eOverridableTokenClientConfig
para separar uma solicitação de vários escopos em várias solicitações menores. - Solicite um novo token quando o token atual expirar ou for revogado.
Trabalhar com vários escopos pode exigir alterações estruturais na sua base de código para solicitar acesso a escopos somente quando necessários, em vez de todos de uma só vez. Isso é conhecido como autorização incremental. Cada solicitação precisa conter o menor escopo possível, e o ideal é ter um único escopo. Veja como processar o consentimento do usuário para mais informações sobre como atualizar seu app para autorização incremental.
Quando um token de acesso expira, o módulo gapi.auth2
recebe automaticamente um novo token de acesso válido para seu app da Web. Para melhorar a segurança do usuário, esse processo automático de atualização de token não é compatível com a biblioteca de serviços do Google Identity. Seu app da Web precisa ser atualizado para detectar um token de acesso expirado
e solicitar um novo. Consulte a seção "Gerenciamento de tokens" abaixo para saber mais.
Fluxo do código de autorização
Adicione um link ou um botão para chamar requestCode()
e solicitar um código de autorização do Google. Para ver um exemplo, consulte
Acionar fluxo de código do OAuth 2.0.
Consulte a seção "Gerenciamento de tokens" abaixo para saber mais sobre como responder a um token de acesso expirado ou revogado.
Gerenciamento de tokens
Tratamento de erros de adição para detectar chamadas com falha da API do Google quando um token de acesso expirado ou revogado é usado e para solicitar um novo token de acesso válido.
Um código de status HTTP com a mensagem de erro 401 Unauthorized
e invalid_token
é retornado pelas APIs do Google quando um token de acesso expirado ou revogado é usado. Para ver um
exemplo, consulte
Resposta de token inválida.
Tokens expirados
Os tokens de acesso são de curta duração e geralmente válidos por apenas alguns minutos.
Revogação de token
O proprietário de uma Conta do Google pode revogar a qualquer momento o consentimento concedido.
Isso invalida os tokens de acesso existentes e atualiza os tokens. A revogação pode ser acionada pela sua plataforma usando revoke()
ou por meio de uma Conta do Google.
Substitua referências de clientes JavaScript do Login do Google: por Serviços de identidade do Google:
Métodos:
getAuthInstance().disconnect()
comgoogle.accounts.oauth2.revoke()
GoogleUser.disconnect()
comgoogle.accounts.oauth2.revoke()
Chame revoke
quando um usuário excluir a conta dele na sua plataforma ou quiser remover o consentimento
para compartilhar dados com seu app.
Solicitação de consentimento do usuário
O Google exibe uma caixa de diálogo de consentimento ao usuário quando o app da Web ou a plataforma de back-end solicita um token de acesso. Veja exemplos de caixas de diálogo de consentimento exibidas pelo Google aos usuários.
Antes de emitir um token de acesso para seu app, é necessário ter uma sessão do Google atual e ativa para solicitar o consentimento do usuário e registrar o resultado. O usuário poderá precisar fazer login em uma Conta do Google se uma sessão existente ainda não tiver sido estabelecida.
Login do usuário
Os usuários podem fazer login em uma Conta do Google em uma guia separada do navegador ou de forma nativa em um navegador ou sistema operacional. Recomendamos que você adicione o recurso Fazer login com o Google no seu site para estabelecer uma sessão ativa entre uma Conta do Google e o navegador quando o usuário abrir o app pela primeira vez. Ao fazer isso, você terá estes benefícios:
- Minimiza o número de vezes que um usuário precisa fazer login, a solicitação de um token de acesso inicia o processo de login da Conta do Google se ainda não existir uma sessão ativa.
- Use diretamente o campo credential
email
do token de ID do JWT como o valor do parâmetrohint
nos objetosCodeClientConfig
ouTokenClientConfig
. Isso é útil principalmente quando a plataforma não tem um sistema de gerenciamento de contas de usuário. - Pesquise e associe uma Conta do Google a uma conta de usuário local na sua plataforma, ajudando a minimizar contas duplicadas.
- Quando uma nova conta local é criada, as caixas de diálogo e o fluxo de inscrição podem ser claramente separados das caixas de diálogo e fluxos de autenticação do usuário. Isso reduz o número de etapas necessárias e melhora a taxa de desistência.
Após o login e antes da emissão de um token de acesso, os usuários precisam dar consentimento para o aplicativo para os escopos solicitados.
Resposta de consentimento e token
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. Ao solicitar acesso a vários escopos, cada um deles é concedido ou rejeitado independentemente dos outros escopos. Com base na escolha do usuário, o app ativa seletivamente os recursos e as funcionalidades que dependem de um escopo individual.
Fluxo implícito
Substitua referências de clientes JavaScript do Login do Google pelos Serviços de identidade do Google:
Objetos:
gapi.auth2.AuthorizeResponse
comTokenClient.TokenResponse
gapi.auth2.AuthResponse
comTokenClient.TokenResponse
Métodos:
GoogleUser.hasGrantedScopes()
comgoogle.accounts.oauth2.hasGrantedAllScopes()
GoogleUser.getGrantedScopes()
comgoogle.accounts.oauth2.hasGrantedAllScopes()
Remova referências de clientes 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
Atualize ou adicione um endpoint de código de autorização à plataforma de back-end seguindo as instruções em como processar o código de autenticação.
Atualize sua plataforma para seguir as etapas descritas no guia Usar o modelo de código a fim de validar a solicitação e receber um token de acesso e de atualização.
Atualize sua plataforma para ativar ou desativar recursos e funcionalidades com base nos escopos individuais que o usuário aprovou seguindo as instruções para autorização incremental e analisar os escopos de acesso concedidos pelo usuário.
Exemplos de fluxo implícito
O jeito antigo
Biblioteca de cliente GAPI
Exemplo da biblioteca de cliente da API do Google para JavaScript em execução no navegador usando uma caixa de diálogo pop-up para consentimento do usuário.
O módulo gapi.auth2
é carregado e usado automaticamente por
gapi.client.init()
e, portanto, fica 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 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 OAuth 2.0
OAuth 2.0 para aplicativos da Web do lado do cliente em execução no navegador usando redirecionamentos para o Google para consentimento do usuário.
Este exemplo mostra chamadas diretas para endpoints do OAuth 2.0 do Google a partir do navegador do usuário e não usa o módulo gapi.auth2
nem uma biblioteca 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>
A nova forma
Somente SIG
Este exemplo mostra somente a biblioteca JavaScript do Google Identity Service usando o modelo de token e a caixa de diálogo pop-up para conseguir o consentimento do usuário. Ele é fornecido para ilustrar o número mínimo de etapas necessárias para configurar um cliente, solicitar e receber 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 async/await
Este exemplo mostra como adicionar a biblioteca do Google Identity Service
usando o modelo de token,
remover o módulo gapi.auth2
e chamar uma API usando a
biblioteca de cliente da API Google para JavaScript.
As promessas, assíncronas e de espera são usadas para aplicar a ordem de carregamento da biblioteca e detectar e repetir erros de autorização. Uma chamada de API é feita apenas depois que um token de acesso válido está disponível.
Espera-se que os usuários pressionem o botão 'Mostrar Agenda' quando o token de acesso estiver ausente no momento do carregamento da página ou posteriormente, após a expiração do token.
<!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>
Retorno de chamada de GAPI
Este exemplo mostra como adicionar a biblioteca do Google Identity Service
usando o modelo de token,
remover o módulo gapi.auth2
e chamar uma API usando a
biblioteca de cliente da API Google para JavaScript.
As variáveis são usadas para aplicar a ordem de carregamento da biblioteca. As chamadas de GAPI são feitas dentro do callback depois que um token de acesso válido é retornado.
Espera-se que os usuários pressionem o botão "Mostrar agenda" quando a página for carregada pela primeira vez e 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 an 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 de código de autorização
A UX pop-up da biblioteca de serviços do Google Identity pode usar um redirecionamento de URL para retornar um código de autorização diretamente ao endpoint do token de back-end ou um gerenciador de callback JavaScript em execução no navegador do usuário, que envia a resposta à plataforma. Em ambos os casos, a plataforma de back-end concluirá o fluxo do OAuth 2.0 para receber um token válido de atualização e acesso.
O jeito antigo
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 com 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 com servidor da Web para enviar um código de autorização do navegador do usuário à plataforma de back-end. Consentimento do usuário gerenciado 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 <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();
}
A nova forma
UX de SIG GIS
Neste exemplo, mostramos apenas a biblioteca JavaScript do Google Identity Service usando o modelo de código de autorização em uma caixa de diálogo pop-up para que o usuário consenta e o gerenciador de callback receba o código de autorização do Google. Ele é fornecido para ilustrar o número mínimo de etapas necessárias para configurar um cliente, receber consentimento e enviar um código de autorização para a plataforma de back-end.
<!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=' + 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 de código de autorização é compatível com os modos de UX de pop-up e redirecionamento para enviar um código de autorização por usuário ao endpoint hospedado pela 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
O Google Identity Services é uma única biblioteca JavaScript usada para autenticação e autorização do usuário que consolida e substitui recursos e funcionalidades encontrados em várias bibliotecas e módulos diferentes:
O que fazer ao migrar para o Identity Services:
Biblioteca JS existente | Nova biblioteca JS | Observações |
---|---|---|
apis.google.com/js/api.js |
accounts.google.com/gsi/client |
Adicione uma nova biblioteca e siga o fluxo implícito. |
apis.google.com/js/client.js |
accounts.google.com/gsi/client |
Adicione uma nova biblioteca e o fluxo de código de autorização. |
Referência rápida da biblioteca
Comparação de objetos e métodos entre a biblioteca de cliente JavaScript antiga do Login do Google e a biblioteca Novo Serviços de identidade do Google e Observações com informações e ações adicionais a serem executadas durante a migração.
Antiga | 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 | Substitua "old" por "new". A revogação também pode ocorrer em https://myaccount.google.com/permissions. |
GoogleAuth.grantOfflineAccess() | Remover o fluxo de código de autorização. | |
GoogleAuth.isSignedIn.get() | Remover | |
GoogleAuth.isSignedIn.listen(). | Remover | |
GoogleAuth.signIn(). | Remover | |
GoogleAuth.signOut(). | Remover | |
GoogleAuth.then() | Remover | |
Objeto GoogleUser e métodos associados: | ||
GoogleUser.disconnect(). | google.accounts.id.revoke (em inglês) | Substitua "old" por "new". A revogação também pode ocorrer em https://myaccount.google.com/permissions. |
GoogleUser.getAuthResponse(). | requestCode() ou requestAccessToken() | Substituir antigo por novo |
GoogleUser.getBasicProfile(). | Remover. Use o token de código em Migrar do Login do Google. | |
GoogleUser.getGRANTedScopes(). | hasGrantedAnyScope() | Substituir antigo por novo |
GoogleUser.getHostedDomain(). | Remover | |
GoogleUser.getId(). | Remover | |
GoogleUser.grantOfflineAccess() | Remover o fluxo de 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 os 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() ou requestAccessToken() | Substituir antigo por novo |
gapi.auth2.ClientConfig(). | TokenClientConfig ou CodeClientConfig | Substituir antigo por novo |
gapi.auth2.getAuthInstance() | Remover | |
gapi.auth2.init() | initTokenClient() ou initCodeClient() | Substituir antigo por novo |
Objeto gapi.auth2.OfflineAccessOptions | Remover | |
Objeto gapi.auth2.SignInOptions | Remover | |
Objeto gapi.signin2 e métodos associados: | ||
gapi.signin2.render() | Remover. O carregamento do DOM do HTML do elemento g_id_signin ou da chamada JS para google.accounts.id.renderButton aciona o login do usuário para uma Conta do Google. |
Exemplos de credenciais
Credenciais existentes
A biblioteca da plataforma de Login do Google, a biblioteca de cliente de APIs 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 uma única 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 do Google Identity Services
A biblioteca do Google Identity Services 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 quando usado 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 um 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"
}
}