1. Home
  2. Server
  3. Authenticate with a backend server | Google Sign-In for Websites

Authenticate with a backend server | Google Sign-In for Websites

Rsdaa 14/01/2022 247

如果您将 Google Sign-In 用于与后端服务器通信的应用或网站,您可能需要识别服务器上当前登录的用户。为了安全地执行此操作,在用户成功登录后,使用 HTTPS 将用户的 ID 令牌发送到您的服务器。然后,在服务器端验证ID令牌的完整性,并使用令牌中包含的用户信息建立会话或创建新帐户。

警告:不接受普通的用户ID,如你可以用得到GoogleUser.getId() method ,您的后端服务器上。修改后的客户端应用程序可以将任意用户 ID 发送到您的服务器以模拟用户,因此您必须改为使用可验证的 ID 令牌来安全地获取服务器端登录用户的用户 ID。

将 ID 令牌发送到您的服务器

用户成功登录后,获取用户的 ID 令牌:

function onSignIn(googleUser) {var id_token = googleUser.getAuthResponse().id_token;...}

然后,使用 HTTPS POST 请求将 ID 令牌发送到您的服务器:

var xhr = new XMLHttpRequest();xhr.open('POST', 'https://yourbackend.example.com/tokensignin');xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');xhr.onload = function() {console.log('Signed in as: ' + xhr.responseText);};xhr.send('idtoken=' + id_token);

验证 ID 令牌的完整性

通过 HTTPS POST 收到 ID 令牌后,您必须验证令牌的完整性。

To verify that the token is valid, ensure that the followingcriteria are satisfied:

The ID token is properly signed by Google. Use Google's public keys(available inJWK orPEM format)to verify the token's signature. These keys are regularly rotated; examinethe Cache-Control header in the response to determine whenyou should retrieve them again.The value of aud in the ID token is equal to one of your app'sclient IDs. This check is necessary to prevent ID tokens issued to a maliciousapp being used to access data about the same user on your app's backend server.The value of iss in the ID token is equal toaccounts.google.com or https://accounts.google.com.The expiry time (exp) of the ID token has not passed.If you want to restrict access to only members of your G Suite domain,verify that the ID token has an hd claim that matches your GSuite domain name.

Rather than writing your own code to perform these verification steps, we stronglyrecommend using a Google API client library for your platform, or a general-purposeJWT library. For development and debugging, you can call our tokeninfovalidation endpoint.

Using a Google API Client Library

Using one of the Google API Client Libraries (e.g.Java,Node.js,PHP,Python)is the recommended way to validate Google ID tokens in a production environment.

To validate an ID token in Java, use the GoogleIdTokenVerifier object. For example:

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 identifierString userId = payload.getSubject();System.out.println("User ID: " + userId);// Get profile information from payloadString 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.");}

The GoogleIdTokenVerifier.verify() method verifies the JWTsignature, the aud claim, the iss claim, and theexp claim.

If you want to restrict access to only members of your G Suite domain,also verify the hd claim by checking the domain namereturned by the Payload.getHostedDomain() method.

To validate an ID token in Node.js, use the Google Auth Library for Node.js.Install the library:

npm install google-auth-library --saveThen, call the verifyIdToken() function. For example:const {OAuth2Client} = require('google-auth-library');const client = new OAuth2Client(CLIENT_ID);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 request specified a G Suite domain:// const domain = payload['hd'];}verify().catch(console.error);

The verifyIdToken function verifiesthe JWT signature, the aud claim, the exp claim,and the iss claim.

If you want to restrict access to only members of your G Suite domain,also verify the hd claim matches your G Suite domain name.

To validate an ID token in PHP, use the Google API Client Library for PHP.Install the library (for example, using Composer):

composer require google/apiclientThen, call the verifyIdToken() function. For example: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 request specified a G Suite domain://$domain = $payload['hd'];} else {// Invalid ID token}

The verifyIdToken function verifiesthe JWT signature, the aud claim, the exp claim,and the iss claim.

If you want to restrict access to only members of your G Suite domain,also verify the hd claim matches your G Suite domain name.

To validate an ID token in Python, use theverify_oauth2_tokenfunction. For example:

from google.oauth2 import id_tokenfrom 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 auth request is from a G Suite domain:# if idinfo['hd'] != GSUITE_DOMAIN_NAME:# raise ValueError('Wrong hosted domain.')# ID token is valid. Get the user's Google Account ID from the decoded token.userid = idinfo['sub']except ValueError:# Invalid tokenpass

The verify_oauth2_token function verifies the JWTsignature, the aud claim, and the exp claim.You must also verify the hdclaim (if applicable) by examining the object thatverify_oauth2_token returns. If multiple clients access thebackend server, also manually verify the aud claim.

Calling the tokeninfo endpoint

An easy way to validate an ID token signature for debugging is touse the tokeninfo endpoint. Calling this endpoint involves anadditional network request that does most of the validation for you while you test propervalidation and payload extraction in your own code. It is not suitable for use in productioncode as requests may be throttled or otherwise subject to intermittent errors.

To validate an ID token using the tokeninfo endpoint, make an HTTPSPOST or GET request to the endpoint, and pass your ID token in theid_token parameter.For example, to validate the token "XYZ123", make the following GET request:

https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123

If the token is properly signed and the iss and expclaims have the expected values, you will get a HTTP 200 response, where the bodycontains the JSON-formatted ID token claims.Here's an example response:

{ // 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"}Warning: Once you get these claims, you still need tocheck that the aud claim contains one of your app's client IDs. If it does, thenthe token is both valid and intended for your client, and you can safely retrieve and use theuser's unique Google ID from the sub claim.

If you are a G Suite customer, you might also be interested in the hdclaim, which indicates the hosted domain of the user. This can be used to restrict accessto a resource to only members of certain domains. The absence of this claim indicatesthat the user does not belong to a G Suite hosted domain.

创建帐户或会话

验证令牌后,检查用户是否已在您的用户数据库中。如果是,请为用户建立经过身份验证的会话。如果该用户尚未出现在您的用户数据库中,请根据 ID 令牌负载中的信息创建一个新的用户记录,并为该用户建立一个会话。当您在应用中检测到新创建的用户时,您可以提示用户提供您需要的任何其他个人资料信息。

使用跨帐户保护保护用户的帐户

当您依靠 Google 为用户登录时,您将自动受益于 Google 为保护用户数据而构建的所有安全功能和基础架构。但是,万一用户的 Google 帐户遭到入侵或发生其他一些重大安全事件,您的应用也可能容易受到攻击。为了更好地保护您的帐户从任何重大安全事件,使用跨帐户保护,从谷歌收到安全警报。收到这些事件后,您就可以了解用户 Google 帐户安全性的重要变化,然后您可以对您的服务采取措施以保护您的帐户。


PREV: Hyper-V Virtual CPUs Explained - Altaro

NEXT: A Guide to VPS vs Cloud Hosting: Understanding Five Key ...

Popular Articles

Hot Articles

Navigation Lists

Back to Top