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 帳戶。- @gmail.com
- 為 true 且 hd已設定,則為 Google Workspace 帳戶。email_verified
 - 使用者可以註冊 Google 帳戶,不必使用 Gmail 或 Google Workspace。如果 - email不含- @gmail.com後置字串,且沒有- hd,Google 就不是授權機構,建議使用密碼或其他驗證方法來驗證使用者。- email_verified也可能成立,因為 Google 最初是在建立 Google 帳戶時驗證使用者,但第三方電子郵件帳戶的擁有權可能已變更。- 強烈建議您使用適用於平台的 Google API 用戶端程式庫,或一般用途的 JWT 程式庫,而不要自行編寫程式碼來執行這些驗證步驟。如要進行開發和偵錯,可以呼叫我們的 - tokeninfo驗證端點。- 使用 Google API 用戶端程式庫- 使用其中一個 Google API 用戶端程式庫 (例如 Java、 Node.js、 PHP、 Python) 是在正式環境中驗證 Google ID 權杖的建議做法。 - 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憑證附加資訊不足以確保帳戶是由網域管理 或機構- Node.js - 如要透過 Node.js 驗證 ID 權杖,請使用 Node.js 適用的 Google 驗證程式庫。 安裝程式庫: - 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 代管的網域- 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 代管的網域- 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 憑證。這表示使用者有現有帳戶的存取權。 
- 回訪的聯合式使用者:您可以讓使用者無聲登入。