Se você usa o Login do Google com um app ou site que se comunica com um servidor de back-end, talvez seja necessário identificar o usuário conectado no servidor. Para fazer isso com segurança, depois que um usuário fizer login, envie o token do ID do usuário para o servidor usando HTTPS. Em seguida, no servidor, verifique a integridade do token de ID e use as informações do usuário contidas nele para estabelecer uma sessão ou criar uma nova conta.
Enviar o token do ID para seu servidor
Depois que um usuário fizer login, consiga o token de ID dele:
Swift
GIDSignIn.sharedInstance.signIn(withPresenting: self) { signInResult, error in guard error == nil else { return } guard let signInResult = signInResult else { return } signInResult.user.refreshTokensIfNeeded { user, error in guard error == nil else { return } guard let user = user else { return } let idToken = user.idToken // Send ID token to backend (example below). } }
Objective-C
[GIDSignIn.sharedInstance signInWithPresentingViewController:self completion:^(GIDSignInResult * _Nullable signInResult, NSError * _Nullable error) { if (error) { return; } if (signInResult == nil) { return; } [signInResult.user refreshTokensIfNeededWithCompletion:^(GIDGoogleUser * _Nullable user, NSError * _Nullable error) { if (error) { return; } if (user == nil) { return; } NSString *idToken = user.idToken; // Send ID token to backend (example below). }]; }];
Em seguida, envie o token de ID para o seu servidor com uma solicitação HTTPS POST:
Swift
func tokenSignInExample(idToken: String) { guard let authData = try? JSONEncoder().encode(["idToken": idToken]) else { return } let url = URL(string: "https://yourbackend.example.com/tokensignin")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") let task = URLSession.shared.uploadTask(with: request, from: authData) { data, response, error in // Handle response from your backend. } task.resume() }
Objective-C
NSString *signinEndpoint = @"https://yourbackend.example.com/tokensignin"; NSDictionary *params = @{@"idtoken": idToken}; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:signinEndpoint]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; [request setHTTPMethod:@"POST"]; [request setHTTPBody:[self httpBodyForParamsDictionary:params]]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { if (error) { NSLog(@"Error: %@", error.localizedDescription); } else { NSLog(@"Signed in as %@", data.bytes); } }];
Verificar a integridade do token de ID
Depois de receber o token de ID por HTTPS POST, verifique a integridade do token.
Para verificar se o token é válido, verifique se os critérios a seguir foram atendidos:
- O token de ID é assinado corretamente pelo Google. Use as chaves públicas do Google
(disponíveis no
formato
JWK ou
PEM)
para verificar a assinatura do token. Essas chaves são alternadas regularmente. Examine
o cabeçalho
Cache-Control
na resposta para determinar quando é preciso recuperá-las novamente. - O valor de
aud
no token de ID é igual a um dos IDs do cliente do seu app. Essa verificação é necessária para evitar que tokens de ID emitidos para um app malicioso seja usado para acessar dados sobre o mesmo usuário no servidor de back-end do app. - O valor de
iss
no token de ID é igual aaccounts.google.com
ouhttps://accounts.google.com
. - O prazo de validade (
exp
) do token de ID não passou. - Se você precisar validar se o token de ID representa uma conta de organização do Google Workspace ou do Cloud, verifique a declaração
hd
, que indica o domínio hospedado do usuário. Precisa ser usado para restringir o acesso a um recurso apenas a membros de determinados domínios. A ausência dessa declaração indica que a conta não pertence a um domínio hospedado pelo Google.
Em vez de escrever seu próprio código para realizar essas etapas de verificação, é altamente recomendável usar uma biblioteca de cliente da API do Google para sua plataforma ou uma biblioteca JWT de uso geral. Para desenvolvimento e depuração, é possível chamar nosso endpoint de validação tokeninfo
.
Usar uma biblioteca de cliente das APIs do Google
Usar uma das bibliotecas de cliente das APIs do Google (por exemplo, Java, Node.js, PHP, Python) é a maneira recomendada de validar os tokens de ID do Google em um ambiente de produção.
Para validar um token de ID em Java, use o objeto GoogleIdTokenVerifier. Exemplo:
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; ... GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) // Specify the CLIENT_ID of the app that accesses the backend: .setAudience(Collections.singletonList(CLIENT_ID)) // Or, if multiple clients access the backend: //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3)) .build(); // (Receive idTokenString by HTTPS POST) GoogleIdToken idToken = verifier.verify(idTokenString); if (idToken != null) { Payload payload = idToken.getPayload(); // Print user identifier String userId = payload.getSubject(); System.out.println("User ID: " + userId); // Get profile information from payload String email = payload.getEmail(); boolean emailVerified = Boolean.valueOf(payload.getEmailVerified()); String name = (String) payload.get("name"); String pictureUrl = (String) payload.get("picture"); String locale = (String) payload.get("locale"); String familyName = (String) payload.get("family_name"); String givenName = (String) payload.get("given_name"); // Use or store profile information // ... } else { System.out.println("Invalid ID token."); }
O método GoogleIdTokenVerifier.verify()
verifica a assinatura
JWT, as declarações aud
, iss
e
exp
.
Se você precisar validar que o token de ID representa uma conta de organização do Google Workspace ou do Cloud, verifique a declaração hd
conferindo o nome de domínio
retornado pelo método Payload.getHostedDomain()
. O domínio da declaração
email
não é suficiente para garantir que a conta seja gerenciada por um domínio
ou organização.
Para validar um token de ID no Node.js, use a Biblioteca Google Auth para Node.js. Instale a biblioteca:
npm install google-auth-library --save. Em seguida, chame a função
verifyIdToken()
. Exemplo:
const {OAuth2Client} = require('google-auth-library'); const client = new OAuth2Client(); async function verify() { const ticket = await client.verifyIdToken({ idToken: token, audience: CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend // Or, if multiple clients access the backend: //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3] }); const payload = ticket.getPayload(); const userid = payload['sub']; // If the request specified a Google Workspace domain: // const domain = payload['hd']; } verify().catch(console.error);
A função verifyIdToken
verifica
a assinatura JWT, a declaração aud
, a declaração exp
e a declaração iss
.
Se você precisar validar se o token de ID representa uma conta de organização do Google Workspace ou do Cloud, verifique a declaração hd
, que indica o domínio hospedado do usuário. Precisa ser usado para restringir o acesso a um recurso apenas a membros
de determinados domínios. A ausência dessa declaração indica que a conta não pertence a um domínio hospedado pelo Google.
Para validar um token de ID em PHP, use a biblioteca de cliente de APIs do Google para PHP. Instale a biblioteca (por exemplo, usando o Composer):
composer require google/apiclient. Em seguida, chame a função
verifyIdToken()
. Exemplo:
require_once 'vendor/autoload.php'; // Get $id_token via HTTPS POST. $client = new Google_Client(['client_id' => $CLIENT_ID]); // Specify the CLIENT_ID of the app that accesses the backend $payload = $client->verifyIdToken($id_token); if ($payload) { $userid = $payload['sub']; // If the request specified a Google Workspace domain //$domain = $payload['hd']; } else { // Invalid ID token }
A função verifyIdToken
verifica
a assinatura JWT, a declaração aud
, a declaração exp
e a declaração iss
.
Se você precisar validar se o token de ID representa uma conta de organização do Google Workspace ou do Cloud, verifique a declaração hd
, que indica o domínio hospedado do usuário. Precisa ser usado para restringir o acesso a um recurso apenas a membros
de determinados domínios. A ausência dessa declaração indica que a conta não pertence a um domínio hospedado pelo Google.
Para validar um token de ID em Python, use a função verify_oauth2_token. Exemplo:
from google.oauth2 import id_token from google.auth.transport import requests # (Receive token by HTTPS POST) # ... try: # Specify the CLIENT_ID of the app that accesses the backend: idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID) # Or, if multiple clients access the backend server: # idinfo = id_token.verify_oauth2_token(token, requests.Request()) # if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]: # raise ValueError('Could not verify audience.') # If the request specified a Google Workspace domain # if idinfo['hd'] != DOMAIN_NAME: # raise ValueError('Wrong domain name.') # ID token is valid. Get the user's Google Account ID from the decoded token. userid = idinfo['sub'] except ValueError: # Invalid token pass
A função verify_oauth2_token
verifica a assinatura
JWT, a declaração aud
e a declaração exp
.
Também é preciso verificar a declaração hd
(se aplicável) examinando o objeto retornado por verify_oauth2_token
. Se vários clientes acessarem o
servidor de back-end, verifique também a declaração aud
manualmente.
Como chamar o endpoint tokeninfo
Uma maneira fácil de validar uma assinatura de token de ID para depuração é usar o endpoint tokeninfo
. Chamar esse endpoint envolve uma outra solicitação de rede que faz a maior parte da validação enquanto você testa a validação adequada e a extração de payload no seu próprio código. Ele não é adequado para uso em código de produção, porque as solicitações podem ser limitadas ou sujeitas a erros intermitentes.
Para validar um token de ID usando o endpoint tokeninfo
, faça uma solicitação HTTPS POST ou GET para o endpoint e transmita seu token de ID no parâmetro id_token
.
Por exemplo, para validar o token "XYZ123", faça a seguinte solicitação GET:
https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123
Se o token estiver assinado corretamente e as declarações iss
e exp
tiverem os valores esperados, você receberá uma resposta HTTP 200, em que o corpo contém as declarações de token de ID formatado em JSON.
Veja um exemplo de resposta:
{ // These six fields are included in all Google ID Tokens. "iss": "https://accounts.google.com", "sub": "110169484474386276334", "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "iat": "1433978353", "exp": "1433981953", // These seven fields are only included when the user has granted the "profile" and // "email" OAuth scopes to the application. "email": "testuser@gmail.com", "email_verified": "true", "name" : "Test User", "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg", "given_name": "Test", "family_name": "User", "locale": "en" }
Se você precisar confirmar que o token de ID representa uma conta do Google Workspace, verifique
a declaração hd
, que indica o domínio hospedado do usuário. Precisa ser usado para restringir o acesso a um recurso apenas a membros de determinados domínios. A ausência dessa declaração
indica que a conta não pertence a um domínio hospedado do Google Workspace.
Criar uma conta ou sessão
Depois de verificar o token, verifique se o usuário já está no banco de dados de usuários. Se for o caso, estabeleça uma sessão autenticada para o usuário. Se o usuário ainda não estiver no banco de dados, crie um novo registro usando as informações no payload do token de ID e estabeleça uma sessão para o usuário. Você pode solicitar outras informações de perfil necessárias ao detectar um usuário recém-criado no app.
Como proteger as contas dos usuários com a Proteção entre contas
Ao confiar no Google para fazer o login de um usuário, você aproveita automaticamente todos os recursos de segurança e a infraestrutura que o Google criou para proteger os dados do usuário. No entanto, no caso improvável de a Conta do Google do usuário ser comprometida ou de alguma outra ocorrência de segurança significativa, seu app também poderá ficar vulnerável a ataques. Para proteger melhor suas contas contra grandes ocorrências de segurança, use a Proteção entre contas para receber alertas de segurança do Google. Ao receber esses eventos, você confere mudanças importantes na segurança da Conta do Google do usuário e pode tomar medidas no seu serviço para proteger suas contas.