Google 返回 ID 令牌后,会通过 HTTP POST 方法请求(参数名称为 credential)将其提交到您的登录端点。
以下是 Python 语言中的示例,展示了验证和使用 ID 令牌的常规步骤:
- 验证跨站请求伪造 (CSRF) 令牌。当您向登录端点提交凭据时,我们会使用双重提交 Cookie 模式来防范 CSRF 攻击。在每次提交之前,我们都会生成一个令牌。然后,将令牌放入 Cookie 和 POST 正文中,如以下代码示例所示: - csrf_token_cookie = self.request.cookies.get('g_csrf_token') if not csrf_token_cookie: webapp2.abort(400, 'No CSRF token in Cookie.') csrf_token_body = self.request.get('g_csrf_token') if not csrf_token_body: webapp2.abort(400, 'No CSRF token in post body.') if csrf_token_cookie != csrf_token_body: webapp2.abort(400, 'Failed to verify double submit cookie.')
- 验证 ID 令牌。 - 如需验证令牌是否有效,请确保满足以下条件: - ID 令牌已由 Google 正确签名。使用 Google 的公钥(以 JWK 或 PEM 格式提供)验证令牌的签名。这些密钥会定期轮换;请检查响应中的 Cache-Control标头,以确定何时应再次检索这些密钥。
- ID 令牌中的 aud值等于您应用的某个客户端 ID。此检查是必要的,可防止向恶意应用发放的 ID 令牌被用于访问您应用后端服务器上有关同一用户的数据。
- ID 令牌中 iss的值等于accounts.google.com或https://accounts.google.com。
- ID 令牌的到期时间 (exp) 尚未到期。
- 如果您需要验证 ID 令牌是否代表 Google Workspace 或 Cloud 组织账号,可以检查 hd声明,该声明表示用户的托管网域。如果需要将对资源的访问权限限制为仅限特定网域的成员,则必须使用此方法。如果缺少此声明,则表示相应账号不属于 Google 托管网域。
 - 通过使用 - email、- email_verified和- hd字段,您可以确定 Google 是否托管某个电子邮件地址并对其具有权威性。如果 Google 是权威方,则表示用户是合法的账号所有者,您可以跳过密码或其他身份验证方法。- Google 具有权威性的情况: - email带有- @gmail.com后缀,则表示这是 Gmail 账号。
- email_verified为 true 且设置了- hd,则为 Google Workspace 账号。
 - 用户可以注册 Google 账号,而无需使用 Gmail 或 Google Workspace。如果 - email不包含- @gmail.com后缀且- hd不存在,则 Google 不具有权威性,建议使用密码或其他质询方法来验证用户身份。- email_verified也可能为 true,因为 Google 最初在创建 Google 账号时验证了用户身份,但第三方电子邮件账号的所有权可能已发生变化。- 我们强烈建议您使用适用于您平台的 Google API 客户端库或通用 JWT 库,而不是自行编写代码来执行这些验证步骤。对于开发和调试,您可以调用我们的 - tokeninfo验证端点。- 使用 Google API 客户端库- 使用某个 Google API 客户端库(例如 Java、 Node.js、 PHP、 Python) 是在生产环境中验证 Google ID 令牌的推荐方法。 <ph type="x-smartling-placeholder">- </ph> <ph type="x-smartling-placeholder"> - </ph> 。 <ph type="x-smartling-placeholder">- Java - 要在 Java 中验证 ID 令牌,请使用 GoogleIdTokenVerifier 对象。例如: - 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 WEB_CLIENT_ID of the app that accesses the backend: .setAudience(Collections.singletonList(WEB_CLIENT_ID)) // Or, if multiple clients access the backend: //.setAudience(Arrays.asList(WEB_CLIENT_ID_1, WEB_CLIENT_ID_2, WEB_CLIENT_ID_3)) .build(); // (Receive idTokenString by HTTPS POST) GoogleIdToken idToken = verifier.verify(idTokenString); if (idToken != null) { Payload payload = idToken.getPayload(); // Print user identifier. This ID is unique to each Google Account, making it suitable for // use as a primary key during account lookup. Email is not a good choice because it can be // changed by the user. 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."); } - GoogleIdTokenVerifier.verify()方法验证 JWT 签名、- aud声明、- iss声明以及- exp项版权主张。- 如果您需要验证 ID 令牌是否代表 Google Workspace 或 Cloud 组织账号,您可以通过检查域名来验证 - hd所有权声明 由- Payload.getHostedDomain()方法返回。该- email声明不足以保证账号是由网域管理 或组织。- </ph> 。 <ph type="x-smartling-placeholder">- Node.js - 要在 Node.js 中验证 ID 令牌,请使用适用于 Node.js 的 Google Auth 库。 安装该库: - npm install google-auth-library --save - verifyIdToken()函数。例如:- const {OAuth2Client} = require('google-auth-library'); const client = new OAuth2Client(); async function verify() { const ticket = await client.verifyIdToken({ idToken: token, audience: WEB_CLIENT_ID, // Specify the WEB_CLIENT_ID of the app that accesses the backend // Or, if multiple clients access the backend: //[WEB_CLIENT_ID_1, WEB_CLIENT_ID_2, WEB_CLIENT_ID_3] }); const payload = ticket.getPayload(); // This ID is unique to each Google Account, making it suitable for use as a primary key // during account lookup. Email is not a good choice because it can be changed by the user. const userid = payload['sub']; // If the request specified a Google Workspace domain: // const domain = payload['hd']; } verify().catch(console.error); - verifyIdToken函数用于验证 JWT 签名、- aud声明、- exp声明 以及- iss声明。- 如果您需要验证 ID 令牌是否代表 Google Workspace 或 Cloud 组织账号时,您可以查看 - hd声明,该声明表示托管的 用户的网域。将资源访问权限限制为仅允许成员访问时,必须使用此设置 特定网域的用户缺少此声明即表示该账号不属于 Google 托管的域。- </ph> 。 <ph type="x-smartling-placeholder">- PHP - 要在 PHP 中验证 ID 令牌,请使用适用于 PHP 的 Google API 客户端库。 安装该库(例如,使用 Composer): - composer require google/apiclient - verifyIdToken()函数。例如:- require_once 'vendor/autoload.php'; // Get $id_token via HTTPS POST. $client = new Google_Client(['client_id' => $WEB_CLIENT_ID]); // Specify the WEB_CLIENT_ID of the app that accesses the backend $payload = $client->verifyIdToken($id_token); if ($payload) { // This ID is unique to each Google Account, making it suitable for use as a primary key // during account lookup. Email is not a good choice because it can be changed by the user. $userid = $payload['sub']; // If the request specified a Google Workspace domain //$domain = $payload['hd']; } else { // Invalid ID token } - verifyIdToken函数用于验证 JWT 签名、- aud声明、- exp声明 以及- iss声明。- 如果您需要验证 ID 令牌是否代表 Google Workspace 或 Cloud 组织账号时,您可以查看 - hd声明,该声明表示托管的 用户的网域。将资源访问权限限制为仅允许成员访问时,必须使用此设置 特定网域的用户缺少此声明即表示该账号不属于 Google 托管的域。- </ph> - Python - 要在 Python 中验证 ID 令牌,请使用 verify_oauth2_token 函数。例如: - from google.oauth2 import id_token from google.auth.transport import requests # (Receive token by HTTPS POST) # ... try: # Specify the WEB_CLIENT_ID of the app that accesses the backend: idinfo = id_token.verify_oauth2_token(token, requests.Request(), WEB_CLIENT_ID) # Or, if multiple clients access the backend server: # idinfo = id_token.verify_oauth2_token(token, requests.Request()) # if idinfo['aud'] not in [WEB_CLIENT_ID_1, WEB_CLIENT_ID_2, WEB_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. # This ID is unique to each Google Account, making it suitable for use as a primary key # during account lookup. Email is not a good choice because it can be changed by the user. userid = idinfo['sub'] except ValueError: # Invalid token pass - verify_oauth2_token函数验证 JWT 签名、- aud声明和- exp声明。 您还必须验证- hd检查- verify_oauth2_token返回。如果多个客户端访问 后端服务器,另请手动验证- aud声明。
- ID 令牌已由 Google 正确签名。使用 Google 的公钥(以 JWK 或 PEM 格式提供)验证令牌的签名。这些密钥会定期轮换;请检查响应中的 
- 确认令牌有效后,您可以使用 Google ID 令牌中的信息来关联您网站的账号状态: - 未注册的用户:您可以显示注册界面 (UI),以便用户根据需要提供其他个人资料信息。它还允许用户静默创建新账号和已登录的用户会话。 
- 您网站上已有的现有账号:您可以显示一个网页,让最终用户输入密码,并将旧账号与其 Google 凭据相关联。这将确认用户是否有权访问现有账号。 
- 回访的联合用户:您可以静默登录用户。