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
Primeiro, quando o usuário fizer login, solicite o token de ID:
-
Ao configurar o Login do Google, chame o método
requestIdToken
e transmita o ID do cliente da Web do servidor para ele.// Request only the user's ID token, which can be used to identify the // user securely to your backend. This will contain the user's basic // profile (name, profile picture URL, etc) so you should not need to // make an additional call to personalize your application. GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(getString(R.string.server_client_id)) .requestEmail() .build();
-
Quando seu app for iniciado, verifique se o usuário já fez login nele usando o Google, neste ou em outro dispositivo, chamando
silentSignIn
:GoogleSignIn.silentSignIn() .addOnCompleteListener( this, new OnCompleteListener<GoogleSignInAccount>() { @Override public void onComplete(@NonNull Task<GoogleSignInAccount> task) { handleSignInResult(task); } });
-
Se o usuário não puder fazer login silenciosamente, apresente sua experiência normal sem login, oferecendo a opção de fazer login. Quando o usuário fizer login, acesse o
GoogleSignInAccount
dele no resultado da atividade da intent de login:// This task is always completed immediately, there is no need to attach an // asynchronous listener. Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data); handleSignInResult(task);
-
Depois que o usuário fizer login de forma silenciosa ou explícita, receba o token de ID do objeto
GoogleSignInAccount
:private void handleSignInResult(@NonNull Task<GoogleSignInAccount> completedTask) { try { GoogleSignInAccount account = completedTask.getResult(ApiException.class); String idToken = account.getIdToken(); // TODO(developer): send ID Token to server and validate updateUI(account); } catch (ApiException e) { Log.w(TAG, "handleSignInResult:error", e); updateUI(null); } }
Em seguida, envie o token de ID para o seu servidor com uma solicitação HTTPS POST:
HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost("https://yourbackend.example.com/tokensignin"); try { List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); nameValuePairs.add(new BasicNameValuePair("idToken", idToken)); httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = httpClient.execute(httpPost); int statusCode = response.getStatusLine().getStatusCode(); final String responseBody = EntityUtils.toString(response.getEntity()); Log.i(TAG, "Signed in as: " + responseBody); } catch (ClientProtocolException e) { Log.e(TAG, "Error sending ID token to backend.", e); } catch (IOException e) { Log.e(TAG, "Error sending ID token to backend.", e); }
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: critérios sejam atendidos:
- O token de ID está devidamente assinado pelo Google. Usar as chaves públicas do Google
(disponível em
JWK ou
PEM)
para verificar a assinatura do token. Essas chaves são trocadas regularmente. examinar
o cabeçalho
Cache-Control
na resposta para determinar quando você deve recuperá-las novamente. - O valor de
aud
no token de ID é igual a um dos IDs de clientes. Essa verificação é necessária para evitar que os tokens de ID emitidos para um dispositivo app sendo usado para acessar dados sobre o mesmo usuário no servidor de back-end do seu 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 do Google Workspace ou
da organização, verifique a declaração
hd
, que indica o servidor domínio do usuário. Isso deve ser usado ao restringir o acesso a um recurso apenas a membros da determinados domínios. A ausência dessa reivindicação indica que a conta não pertence a Domínio hospedado pelo Google.
Usando os campos email
, email_verified
e hd
, é possível determinar se
O Google hospeda e é autoritativo para um endereço de e-mail. Nos casos em que o Google é confiável,
o usuário é conhecido como o proprietário legítimo da conta, e você pode ignorar a senha ou outras
e métodos de desafio.
Casos em que o Google é confiável:
email
tem o sufixo@gmail.com
. Esta é uma conta do Gmail.- A opção
email_verified
é verdadeira ehd
foi definida. Esta é uma conta do G Suite.
Os usuários podem se registrar para Contas do Google sem usar o Gmail ou o G Suite. Quando
email
não contém um sufixo @gmail.com
e hd
está ausente, o Google não está
com autoridade e senha ou outros métodos de desafio
o usuário. email_verified
também pode ser verdadeiro porque o Google verificou inicialmente o
usuário quando a Conta do Google foi criada, mas a propriedade do terceiro
pode ter mudado desde então.
Em vez de escrever seu próprio código para executar essas etapas de verificação, é altamente
recomendamos o uso de uma biblioteca de cliente de API do Google para sua plataforma ou uma
biblioteca JWT. Para desenvolvimento e depuração, você pode chamar nossa classe tokeninfo
endpoint de validação.
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 forma recomendada de validar tokens de ID do Google em um ambiente de produção.
Para validar um token de ID em Java, use o método 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 o JWT
assinatura, a declaração aud
, a declaração iss
e a
Reivindicação exp
.
Se você precisar validar se o token de ID representa uma conta do Google Workspace ou
conta da organização, você pode verificar a declaração hd
conferindo o nome de domínio
retornados pelo método Payload.getHostedDomain()
. O domínio do
email
reivindicação é insuficiente 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 do Google Auth para Node.js. Instale a biblioteca:
npm install google-auth-library --saveEm 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 do Google Workspace ou
da organização, verifique a declaração hd
, que indica o servidor
domínio do usuário. Precisa ser usado ao restringir o acesso a um recurso apenas para membros
de determinados domínios. A ausência dessa reivindicaçã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/apiclientEm 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 do Google Workspace ou
da organização, verifique a declaração hd
, que indica o servidor
domínio do usuário. Precisa ser usado ao restringir o acesso a um recurso apenas para membros
de determinados domínios. A ausência dessa reivindicação indica que a conta não pertence a
um domínio hospedado pelo Google.
Para validar um token de ID em Python, use o verify_oauth2_token função. 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 o JWT
assinatura, a declaração aud
e a declaração exp
.
Você também precisa verificar a hd
(se aplicável) examinando o objeto que
verify_oauth2_token
retorna. Se vários clientes acessarem o
servidor de back-end, verifique manualmente a declaração aud
.
调用 tokeninfo 端点
为调试验证 ID 令牌签名的一种简单方法是
使用 tokeninfo
端点。调用此端点涉及
这个额外的网络请求会为您完成大部分的验证工作,
验证和载荷提取。不适合在生产环境中使用
因为请求可能会受到限制或出现间歇性错误。
如需使用 tokeninfo
端点验证 ID 令牌,请创建 HTTPS
POST 或 GET 请求发送到端点,并在
id_token
参数。
例如,要验证令牌“XYZ123”,请发出以下 GET 请求:
https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123
如果令牌经过正确签名,并且 iss
和 exp
具有预期值,就会收到 HTTP 200 响应,其中正文
包含 JSON 格式的 ID 令牌声明。
以下是示例响应:
{ // 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" }
如果您需要验证 ID 令牌是否代表 Google Workspace 账号,可以先查看
hd
声明,指示用户的托管网域。只有在以下情况下,
从而仅允许特定网域中的成员访问资源。缺少此声明
表示该账号不属于 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.