Google 的 OAuth 2.0 API 可用於驗證和授權。本文說明我們用於驗證的 OAuth 2.0 實作方式,這項方式符合 OpenID Connect 規格,並已通過 OpenID 認證。使用 OAuth 2.0 存取 Google API 一文中的說明文件也適用於這項服務。如要以互動方式探索這項通訊協定,建議使用 Google OAuth 2.0 Playground。如需 Stack Overflow 的協助,請在問題中加上「google-oauth」標記。
設定 OAuth 2.0
應用程式必須先在 Google Cloud 控制台中設定專案,才能使用 Google 的 OAuth 2.0 驗證系統登入使用者,並取得 OAuth 2.0 憑證、設定重新導向 URI,以及 (選擇性) 自訂使用者在使用者同意畫面中看到的品牌資訊。您也可以使用 Cloud 控制台建立服務帳戶、啟用帳單、設定篩選條件,以及執行其他工作。詳情請參閱 Google Cloud 控制台說明。
取得 OAuth 2.0 憑證
您需要 OAuth 2.0 憑證 (包括用戶端 ID 和用戶端密碼) 才能驗證使用者,並取得 Google API 的存取權。
如要查看特定 OAuth 2.0 憑證的用戶端 ID 和用戶端密鑰,請按一下「選取憑證」文字。在開啟的視窗中,選擇專案和所需憑證,然後按一下「查看」。
您也可以在 Cloud 控制台的「用戶端」頁面中,查看用戶端 ID 和用戶端密鑰:
設定重新導向 URI
您在 Cloud Console 中設定的重新導向 URI,會決定 Google 將回應傳送至何處,以回應您的驗證要求。
如要建立、查看或編輯特定 OAuth 2.0 憑證的重新導向 URI,請按照下列步驟操作:
如果「用戶端」頁面未列出任何用戶端,表示您的專案沒有 OAuth 憑證。如要建立用戶端,請按一下「建立用戶端」。
自訂使用者同意畫面
對使用者而言,OAuth 2.0 驗證體驗包括同意畫面,其中會說明使用者要發布的資訊和適用條款。舉例來說,使用者登入時,系統可能會要求他們授予應用程式電子郵件地址和基本帳戶資訊的存取權。您可以使用 scope 參數要求存取這項資訊,應用程式會在驗證要求中加入這個參數。您也可以使用範圍要求存取其他 Google API。
使用者同意畫面也會顯示品牌資訊,例如產品名稱、標誌和首頁網址。您可以在 Cloud Console 中控管品牌資訊。
如要啟用專案的同意畫面,請按照下列步驟操作:
下列同意聲明對話方塊顯示使用者在要求中同時包含 OAuth 2.0 和 Google 雲端硬碟範圍時,會看到的畫面。(這個一般對話方塊是使用 Google OAuth 2.0 Playground 產生,因此不包含在 Cloud 控制台中設定的品牌資訊)。
存取服務
Google 和第三方提供的程式庫可協助您處理許多實作細節,例如驗證使用者身分和取得 Google API 的存取權。舉例來說,Google Identity 服務 和 Google 用戶端程式庫適用於各種平台。
如果選擇不使用程式庫,請按照本文其餘部分的說明操作,瞭解可用程式庫的基礎 HTTP 請求流程。
驗證使用者
驗證使用者身分時,需要取得並驗證 ID 權杖。ID 權杖是 OpenID Connect 的標準化功能,專為在網路上分享身分主張而設計。
驗證使用者身分並取得 ID 權杖最常用的方法,稱為「伺服器」流程和「隱含」流程。伺服器流程可讓應用程式的後端伺服器驗證使用瀏覽器或行動裝置的人員身分。如果用戶端應用程式 (通常是在瀏覽器中執行的 JavaScript 應用程式) 需要直接存取 API,而非使用後端伺服器,則會使用隱含流程。
本文說明如何執行伺服器流程來驗證使用者。由於在用戶端處理及使用權杖時存在安全風險,隱含流程會複雜許多。如需實作隱含流程,強烈建議使用 Google Identity 服務。
伺服器流程
請務必在 Cloud 控制台中設定應用程式,啟用這些通訊協定並驗證使用者身分。當使用者嘗試使用 Google 帳戶登入時,您需要:
1. 建立防偽狀態權杖
您必須防範要求偽造攻擊,保護使用者安全。第一步是建立專屬工作階段符記,在應用程式和使用者用戶端之間保留狀態。您稍後會將這個不重複的工作階段符記與 Google OAuth 登入服務傳回的驗證回應進行比對,確認要求是由使用者發出,而非惡意攻擊者。這些權杖通常稱為跨網站要求偽造 (CSRF) 權杖。
狀態權杖的理想選擇是使用高品質隨機數字產生器建構的字串,長度約為 30 個字元。另一種是雜湊,這類雜湊是使用後端機密金鑰簽署部分工作階段狀態變數所產生。
下列程式碼示範如何產生專屬工作階段權杖。
PHP
您必須下載 Google API PHP 用戶端程式庫,才能使用這個範例。
// Create a state token to prevent request forgery. // Store it in the session for later validation. $state = bin2hex(random_bytes(128/8)); $app['session']->set('state', $state); // Set the client ID, token state, and application name in the HTML while // serving it. return $app['twig']->render('index.html', array( 'CLIENT_ID' => CLIENT_ID, 'STATE' => $state, 'APPLICATION_NAME' => APPLICATION_NAME ));
Java
您必須下載 Java 適用的 Google API 用戶端程式庫,才能使用這個範例。
// Create a state token to prevent request forgery. // Store it in the session for later validation. String state = new BigInteger(130, new SecureRandom()).toString(32); request.session().attribute("state", state); // Read index.html into memory, and set the client ID, // token state, and application name in the HTML before serving it. return new Scanner(new File("index.html"), "UTF-8") .useDelimiter("\\A").next() .replaceAll("[{]{2}\\s*CLIENT_ID\\s*[}]{2}", CLIENT_ID) .replaceAll("[{]{2}\\s*STATE\\s*[}]{2}", state) .replaceAll("[{]{2}\\s*APPLICATION_NAME\\s*[}]{2}", APPLICATION_NAME);
Python
您必須下載 Google API Python 專用用戶端程式庫,才能使用這個範例。
# Create a state token to prevent request forgery. # Store it in the session for later validation. state = hashlib.sha256(os.urandom(1024)).hexdigest() session['state'] = state # Set the client ID, token state, and application name in the HTML while # serving it. response = make_response( render_template('index.html', CLIENT_ID=CLIENT_ID, STATE=state, APPLICATION_NAME=APPLICATION_NAME))
2. 向 Google 傳送驗證要求
下一步是使用適當的 URI 參數,建立 HTTPS GET 要求。請注意,這個程序的所有步驟都使用 HTTPS,而非 HTTP,因為系統會拒絕 HTTP 連線。您應使用 authorization_endpoint 中繼資料值,從探索文件擷取基本 URI。以下討論假設基本 URI 為 https://accounts.google.com/o/oauth2/v2/auth。
如為基本要求,請指定下列參數:
client_id,可從 Cloud Console 的「用戶端」頁面取得。- ,在基本授權碼流程要求中應為
code。(詳情請參閱response_type。)response_type scope,在基本要求中應為openid email。 (詳情請參閱scope。)redirect_uri應為伺服器上的 HTTP 端點,用於接收 Google 的回覆。這個值必須與 Cloud 控制台「憑證」頁面中,OAuth 2.0 用戶端的其中一個已授權重新導向 URI 完全相符。如果這個值與授權 URI 不符,要求就會失敗並產生redirect_uri_mismatch錯誤。state應包含防偽工作階段專屬權杖的值,以及使用者返回應用程式時復原環境所需的任何其他資訊,例如起始網址。(詳情請參閱state。)nonce是應用程式產生的隨機值,可啟用重播防護機制。login_hint可以是使用者的電子郵件地址或sub字串,相當於使用者的 Google ID。如果您未提供login_hint,且使用者已登入,同意畫面會要求核准將使用者的電子郵件地址發布給您的應用程式。(詳情請參閱login_hint。)- 使用
hd參數,為與 Google Workspace 或 Cloud 機構相關聯的特定網域使用者,最佳化 OpenID Connect 流程 (詳情請參閱hd)。
以下是完整的 OpenID Connect 驗證 URI 範例,為方便閱讀,已加入換行符和空格:
https://accounts.google.com/o/oauth2/v2/auth? response_type=code& client_id=424911365001.apps.googleusercontent.com& scope=openid%20email& redirect_uri=https%3A//developers.google.com/oauthplayground& state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2-login-demo.example.com%2FmyHome& login_hint=jsmith@example.com& nonce=0394852-3190485-2490358& hd=example.com
如果應用程式要求提供任何新的使用者資訊,或是要求存取使用者先前未核准的帳戶,就必須徵求使用者同意。
3. 確認防偽狀態權杖
回應會傳送至您在要求中指定的 redirect_uri。所有回應都會以查詢字串的形式傳回:
https://developers.google.com/oauthplayground?state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foa2cb.example.com%2FmyHome&code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&scope=openid%20email%20https://www.googleapis.com/auth/userinfo.email
根據 RFC 6749,用戶端「必須」忽略無法辨識的回應參數。在伺服器上,您必須確認從 Google 收到的 state 與您在步驟 1 中建立的工作階段符記相符。這項來回驗證有助於確認要求是由使用者發出,而非惡意指令碼。
下列程式碼示範如何確認您在步驟 1 中建立的工作階段權杖:
PHP
您必須下載 Google API PHP 用戶端程式庫,才能使用這個範例。
// Ensure that there is no request forgery going on, and that the user // sending us this connect request is the user that was supposed to. if ($request->get('state') != ($app['session']->get('state'))) { return new Response('Invalid state parameter', 401); }
Java
您必須下載 Java 適用的 Google API 用戶端程式庫,才能使用這個範例。
// Ensure that there is no request forgery going on, and that the user // sending us this connect request is the user that was supposed to. if (!request.queryParams("state").equals( request.session().attribute("state"))) { response.status(401); return GSON.toJson("Invalid state parameter."); }
Python
您必須下載 Google API Python 專用用戶端程式庫,才能使用這個範例。
# Ensure that the request is not a forgery and that the user sending # this connect request is the expected user. if request.args.get('state', '') != session['state']: response = make_response(json.dumps('Invalid state parameter.'), 401) response.headers['Content-Type'] = 'application/json' return response
4. 使用 code 交換存取權杖和 ID 權杖
回應會包含 code 參數,這是伺服器可交換存取權杖和 ID 權杖的一次性授權碼。伺服器會傳送 HTTPS POST 要求,進行這項交換作業。POST 要求會傳送至權杖端點,您應使用 token_endpoint 中繼資料值,從導覽文件擷取該端點。以下討論假設端點為 https://oauth2.googleapis.com/token。要求必須在 POST 主體中包含下列參數:
| 欄位 | |
|---|---|
code |
初始要求傳回的授權碼。 |
client_id |
如「取得 OAuth 2.0 憑證」一文所述,從 Cloud 控制台的「用戶端」頁面取得的用戶端 ID。 |
client_secret |
從 Cloud Console 的「用戶端」頁面取得的用戶端密鑰,如「取得 OAuth 2.0 憑證」一文所述。 |
redirect_uri |
在 Cloud Console 的「用戶端」頁面中,為指定 client_id 設定的已授權重新導向 URI,如「設定重新導向 URI」一文所述。 |
grant_type |
這個欄位必須包含 authorization_code 值,如 OAuth 2.0 規格所定義。 |
實際要求可能如下列範例所示:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7& client_id=your-client-id& client_secret=your-client-secret& redirect_uri=https%3A//developers.google.com/oauthplayground& grant_type=authorization_code
這項要求的成功回應會包含 JSON 陣列中的下列欄位:
| 欄位 | |
|---|---|
access_token |
可傳送至 Google API 的權杖。 |
expires_in |
存取權杖的剩餘生命週期 (以秒為單位)。 |
id_token |
內含使用者身分資訊的 JWT,由 Google 進行數位簽署。 |
scope |
access_token授予的存取權範圍,以不區分大小寫的字串清單表示,並以空格分隔。 |
token_type |
識別傳回的權杖類型。目前這個欄位的值一律為 Bearer。 |
refresh_token |
(選填)
只有在驗證要求中, |
5. 從 ID 權杖取得使用者資訊
ID 權杖是 JWT (JSON Web Token),也就是經過加密簽署的 Base64 編碼 JSON 物件。通常,您必須先驗證 ID 權杖,才能使用該權杖,但由於您是透過無中介的 HTTPS 管道直接與 Google 通訊,並使用用戶端密鑰向 Google 驗證身分,因此可以確信收到的權杖確實來自 Google 且有效。如果伺服器將 ID 權杖傳遞給應用程式的其他元件,請務必讓其他元件先驗證權杖,再使用權杖。
由於大多數 API 程式庫會將驗證與解碼 base64url 編碼值和剖析 JSON 的工作合併,因此您在存取 ID 權杖中的宣告時,可能還是會驗證權杖。
ID 權杖的酬載
ID 權杖是包含一組名稱/值配對的 JSON 物件。以下為範例,格式經過調整,方便閱讀:
{ "iss": "https://accounts.google.com", "azp": "1234987819200.apps.googleusercontent.com", "aud": "1234987819200.apps.googleusercontent.com", "sub": "10769150350006150715113082367", "at_hash": "HK6E_P6Dh8Y93mRNtsDB1Q", "hd": "example.com", "email": "jsmith@example.com", "email_verified": "true", "iat": 1353601026, "exp": 1353604926, "nonce": "0394852-3190485-2490358" }
Google ID 權杖可能含有下列欄位 (稱為憑證附加資訊):
| 聲明著作權 | 自行提供 | 說明 |
|---|---|---|
aud |
一律 | 這個 ID 權杖的適用對象。此屬性必須是應用程式的 OAuth 2.0 用戶端 ID。 |
exp |
一律 | ID 權杖的到期時間,到期後不得再接受。以 Unix Epoch 紀元時間 (整數秒數) 表示。 |
iat |
一律 | ID 權杖的核發時間,以 Unix 紀元時間 (整數秒數) 表示。 |
iss |
一律 | 回覆核發者的核發者 ID。一律從 https://accounts.google.com或 accounts.google.com 取得 Google ID 權杖。 |
sub |
一律 | 使用者的專屬 ID,必須別於任何其他 Google 帳戶,且不得重複使用。Google 帳戶可在不同時間點使用多個電子郵件地址,但 sub 值一律維持不變。在應用程式中,請使用 sub 做為使用者的專屬 ID 鍵。長度上限為 255 個區分大小寫的 ASCII 字元。 |
amr |
字串的 JSON 陣列,用於識別登入 Google 帳戶時使用的驗證方法。如果存在,則包含一或多個可能的 [IANA.AMR] 值:
amr 聲明,且已在設定中啟用時,才會顯示。
|
|
auth_time |
使用者驗證時間,以 JSON 數字表示,代表自 Unix 紀元 (1970 年 1 月 1 日 00:00:00 UTC) 經過的秒數。如果驗證要求中包含 auth_time 聲明,且已在設定中啟用,系統就會提供這項資訊。
|
|
at_hash |
存取權杖雜湊值。驗證存取權杖是否與 ID 權杖相關聯。如果 ID 權杖是在伺服器流程中以 access_token 值核發,系統一律會納入這項聲明。這個聲明可做為替代機制,防範跨網站偽造要求攻擊,但如果您按照步驟 1 和步驟 3 操作,就不必驗證存取權杖。 |
|
azp |
授權表示器的 client_id。只有當 ID 權杖的要求者與 ID 權杖的目標對象不同時,才需要使用這項憑證附加資訊。如果是在 Google 中使用混合型應用程式,若網頁應用程式和 Android 應用程式的 OAuth 2.0 client_id 不同,但共用同一項 Google API 專案,則可能會發生這種情況。 |
|
email |
使用者的電子郵件地址。只有在要求中加入 email 範圍時,才會提供這項資訊。這項聲明的價值可能不是這個帳戶專屬,且可能會隨時間變更,因此不應將這個值做為連結至使用者記錄的主要 ID。您也無法依據 email 聲明中的網域,識別 Google Workspace 或 Cloud 機構的使用者,請改用 hd 聲明。
|
|
email_verified |
如果使用者的電子郵件地址已完成驗證,則為 true;否則傳回 false。 | |
family_name |
使用者的姓氏。如果存在 name 聲明,可能會提供此屬性。 |
|
given_name |
使用者的名字。如果存在 name 聲明,可能會提供此屬性。 |
|
hd |
與使用者 Google Workspace 或 Cloud 機構相關聯的網域。只有在使用者屬於 Google Cloud 機構時才會提供。如要將資源存取權限制為僅限特定網域的成員,您必須檢查這項聲明。如果沒有這項聲明,表示帳戶不屬於 Google 代管網域。 | |
locale |
使用者的語言代碼,以 BCP 47 語言標記表示。如果存在 name 聲明,可能會提供此屬性。 |
|
name |
以可顯示格式呈現的使用者全名。可能在下列情況提供:
如果存在 |
|
nonce |
您的應用程式在驗證要求中提供的 nonce 值。您必須確保這個值只會出現一次,以防範重送攻擊。 |
|
picture |
使用者個人資料相片的網址。可能在下列情況提供:
如果存在 |
|
profile |
使用者的個人資料頁面網址。可能在下列情況提供:
如果存在 |
6. 驗證使用者
從 ID 權杖取得使用者資訊後,您應查詢應用程式的使用者資料庫。如果資料庫中已有該使用者,且 Google API 回應符合所有登入規定,您就應為該使用者啟動應用程式工作階段。
如果使用者不存在於使用者資料庫中,您應將使用者重新導向至新使用者註冊流程。您或許可以根據從 Google 收到的資訊自動註冊使用者,或至少預先填寫註冊表單中許多必填欄位。除了 ID 權杖中的資訊,您還可以在使用者個人資料端點取得其他使用者個人資料資訊。
進階主題
以下各節將詳細說明 Google OAuth 2.0 API。這項資訊適用於對驗證和授權有進階需求的開發人員。
存取其他 Google API
使用 OAuth 2.0 進行驗證的優點之一,是應用程式在驗證使用者的同時,可以取得代表使用者使用其他 Google API 的權限 (例如 YouTube、Google 雲端硬碟、日曆或聯絡人)。如要這麼做,請在傳送給 Google 的驗證要求中,加入您需要的其他範圍。舉例來說,如要在驗證要求中加入使用者的年齡層,請傳遞 openid email https://www.googleapis.com/auth/profile.agerange.read 的範圍參數。系統會在同意畫面上適當提示使用者。您從 Google 收到的存取權杖,可讓應用程式存取您要求並獲准存取的所有 API 範圍。
更新權杖
在 API 存取要求中,您可以要求在code交換期間傳回重新整理權杖。更新權杖可讓應用程式在使用者不在應用程式中時,持續存取 Google API。如要要求更新權杖,請在驗證要求中,將 access_type 參數設為 offline。
注意事項:
- 請務必安全地永久儲存重新整理權杖,因為您只能在首次執行程式碼交換流程時取得重新整理權杖。
- 核發的重新整理權杖數量設有限制:每個用戶端/使用者組合一個限制,所有用戶端的使用者則共用一個限制。如果應用程式要求的重新整理權杖過多,可能會達到這些限制,屆時較舊的重新整理權杖就會停止運作。
詳情請參閱「重新整理存取權杖 (離線存取)」。
提示使用者重新提供同意聲明
將驗證要求中的 prompt 參數設為 consent,即可提示使用者重新授權應用程式。如果包含 prompt=consent,應用程式每次要求授權存取範圍時,都會顯示同意畫面,即使先前已將所有範圍授予 Google API 專案也一樣。因此,請僅在必要時加入 prompt=consent。
如要進一步瞭解 prompt 參數,請參閱「驗證 URI 參數」表格中的 prompt。
驗證 URI 參數
下表更完整地說明 Google OAuth 2.0 驗證 API 接受的參數。
| 參數 | 必填 | 說明 | ||||||
|---|---|---|---|---|---|---|---|---|
client_id |
(必填) | 從 Cloud 控制台的「用戶端」頁面取得的用戶端 ID 字串,如「取得 OAuth 2.0 憑證」一文所述。 | ||||||
nonce |
(必填) | 應用程式產生的隨機值,可啟用重送保護機制。 | ||||||
response_type |
(必填) | 如果值為 code,系統會啟動基本授權碼流程,並要求向權杖端點提供 POST,以取得權杖。如果值為 token id_token 或 id_token token,系統會啟動隱含流程,因此您必須在重新導向 URI 中使用 JavaScript,從 URI #fragment ID 擷取權杖。 |
||||||
redirect_uri |
(必填) | 決定要將回應傳送至何處。這個參數的值必須與您在 Cloud 控制台「用戶端」頁面中設定的其中一個授權重新導向值完全相符 (包括 HTTP 或 HTTPS 通訊協定、大小寫和尾端「/」,如有)。 | ||||||
scope |
(必填) | 範圍參數開頭必須為 如果存在 如果存在 除了這些 OpenID 專屬範圍,範圍引數也可以包含其他範圍值。所有範圍值都必須以半形空格分隔。舉例來說,如要取得使用者 Google 雲端硬碟中每個檔案的存取權,範圍參數可能是 如要瞭解可用範圍,請參閱「Google API 適用的 OAuth 2.0 範圍」,或您想使用的 Google API 說明文件。 |
||||||
state |
(選用,但強烈建議) | 通訊協定中來回傳輸的不透明字串;也就是說,在 Basic 流程中,這個字串會以 URI 參數的形式傳回,在隱含流程中,則會以 URI
|
||||||
access_type |
(選填) | 允許的值為 offline 和 online。相關影響請參閱「離線存取」一文。如果要求存取權杖,除非指定 offline 值,否則用戶端不會收到重新整理權杖。 |
||||||
claims |
(選填) |
claims 參數可用來指定要在使用者資訊端點或驗證要求 ID 權杖回應類型中加入的一或多個選用欄位。這個值是包含回應類型和要求聲明的 JSON 物件。Google 伺服器接受下列聲明要求:
|
||||||
display |
(選填) | ASCII 字串值,用於指定授權伺服器顯示驗證和同意聲明使用者介面頁面的方式。Google 伺服器會接受下列指定值,但這些值不會對通訊協定流程行為造成任何影響:page、popup、touch 和 wap。 |
||||||
hd |
(選填) | 簡化 Google Cloud 機構擁有的帳戶登入程序。加入 Google Cloud 機構網域 (例如 mycollege.edu) 後,您就能指出帳戶選取 UI 應針對該網域的帳戶進行最佳化。如要針對一般 Google Cloud 組織帳戶 (而非單一 Google Cloud 組織網域) 進行最佳化,請將值設為星號 ( 請勿依賴這項 UI 最佳化功能控管應用程式存取權,因為用戶端要求可能會遭到修改。請務必驗證傳回的 ID 權杖是否具有符合預期的 |
||||||
include_granted_scopes |
(選填) | 如果這個參數的值為 true,且授權要求獲得核准,授權將包含先前授予這個使用者/應用程式組合的其他範圍授權;請參閱「增量授權」。
請注意,您無法透過已安裝應用程式流程進行增量授權。 |
||||||
login_hint |
(選填) | 應用程式知道要驗證哪個使用者時,可以將這個參數當做提示提供給驗證伺服器。傳遞這項提示會隱藏帳戶選擇器,並預先填入登入表單的電子郵件方塊,或選取適當的會話 (如果使用者採用多重登入),有助於避免應用程式登入錯誤使用者帳戶時發生的問題。這個值可以是電子郵件地址或 sub 字串,兩者都等同於使用者的 Google ID。 |
||||||
prompt |
(選填) | 以空格分隔的字串值清單,指定授權伺服器是否提示使用者重新驗證及同意。可能的值如下:
如未指定任何值,且使用者先前未授權存取,系統就會向使用者顯示同意畫面。 |
||||||
hl |
(選填) | BCP 47 語言代碼,用於指定登入、帳戶選擇器和同意畫面使用的顯示語言。如果未提供這個參數,系統預設會使用使用者的 Google 帳戶或瀏覽器設定。舉例來說,如要以英式英文顯示使用者介面,請將參數設為 en-GB。 |
||||||
驗證 ID 權杖
除非您確定 ID 權杖直接來自 Google,否則必須在伺服器上驗證所有 ID 權杖。舉例來說,伺服器必須驗證從用戶端應用程式收到的任何 ID 權杖是否為真。
以下是您可能會將 ID 權杖傳送至伺服器的常見情況:
- 在需要驗證的要求中傳送 ID 權杖。ID 權杖會告知您提出要求的使用者,以及授予該 ID 權杖的用戶端。
ID 權杖屬於私密資訊,如果遭到攔截,可能會遭到濫用。您必須確保這些權杖受到安全處理,只透過 HTTPS 傳輸,且只使用 POST 資料或要求標頭中的權杖。如果將 ID 權杖儲存在伺服器上,也必須安全地儲存。
ID 權杖的實用之處在於,您可以將權杖傳遞至應用程式的不同元件。這些元件可將 ID 權杖做為輕量型驗證機制,驗證應用程式和使用者。不過,您必須先驗證 ID 權杖,才能使用其中的資訊,或將其做為使用者已通過驗證的聲明。
驗證 ID 權杖需要執行幾個步驟:
- 確認 ID 權杖是由簽發者正確簽署。Google 核發的權杖會使用 Discovery 文件的
jwks_uri中繼資料值所指定 URI 中的其中一個憑證簽署。 - 確認 ID 權杖中
iss聲明的值等於https://accounts.google.com或accounts.google.com。 - 確認 ID 權杖中
aud聲明的值等於應用程式的用戶端 ID。 - 確認 ID 權杖的到期時間 (
exp要求) 尚未到期。 - 如果您在要求中指定 hd 參數值,請確認 ID 權杖具有
hd聲明,且該聲明與 Google Cloud 機構相關聯的已接受網域相符。
步驟 2 到 5 只涉及字串和日期比較,相當簡單,因此我們不會在此詳述。
第一個步驟較為複雜,需要檢查加密簽章。為進行偵錯,您可以透過 Google 的 tokeninfo 端點,與伺服器或裝置上實作的本機處理程序進行比較。假設您的 ID 權杖值為
XYZ123。然後取消參照 URI https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123。如果權杖簽章有效,回應會是 JWT 酬載,以解碼的 JSON 物件形式呈現。
tokeninfo 端點適用於偵錯,但為了進行生產,請從金鑰端點擷取 Google 的公開金鑰,並在本機執行驗證。您應使用 jwks_uri 中繼資料值,從導覽文件擷取金鑰 URI。對偵錯端點的要求可能會受到節流,或發生間歇性錯誤。
由於 Google 不常變更公開金鑰,因此您可以使用 HTTP 回應的快取指令快取金鑰,而且在絕大多數情況下,執行本機驗證的效率遠高於使用 tokeninfo 端點。這項驗證需要擷取及剖析憑證,並進行適當的加密編譯呼叫來檢查簽章。幸運的是,有許多語言提供經過充分偵錯的程式庫,可完成這項工作 (請參閱 jwt.io)。
取得使用者個人資料資訊
如要取得使用者的其他個人資料資訊,可以使用存取權杖 (應用程式在驗證流程中收到的權杖) 和 OpenID Connect 標準:
如要符合 OpenID 規範,您必須在驗證要求中加入
openid profile範圍值。如要納入使用者的電子郵件地址,可以指定
email的額外範圍值。如要同時指定profile和email,請在驗證要求 URI 中加入下列參數:scope=openid%20profile%20email
- 將存取權杖新增至授權標頭,並對使用者資訊端點提出 HTTPS
GET要求。您應使用userinfo_endpoint中繼資料值,從導覽文件擷取使用者資訊端點。如OpenID Connect Standard Claims和導覽文件claims_supported中繼資料值所述,userinfo 回應包含使用者的相關資訊。使用者或所屬機構可能會選擇提供或隱藏特定欄位,因此您可能無法取得授權存取範圍內每個欄位的資訊。
導覽文件
OpenID Connect 通訊協定規定必須使用多個端點驗證使用者,以及要求資源,包括權杖、使用者資訊和公開金鑰。
為簡化實作程序並提高彈性,OpenID Connect 允許使用「導覽文件」,這份 JSON 文件位於已知位置,內含鍵/值組合,可提供 OpenID Connect 供應商設定的詳細資料,包括授權、權杖、撤銷、使用者資訊和公開金鑰端點的 URI。Google OpenID Connect 服務的導覽文件可從下列網址擷取:
https://accounts.google.com/.well-known/openid-configuration
如要使用 Google 的 OpenID Connect 服務,您應將探索文件 URI (https://accounts.google.com/.well-known/openid-configuration) 硬式編碼至應用程式中。應用程式會擷取文件、套用回應中的快取規則,然後視需要從中擷取端點 URI。舉例來說,如要驗證使用者,您的程式碼會擷取 authorization_endpoint 中繼資料值 (以下範例中的 https://accounts.google.com/o/oauth2/v2/auth),做為傳送至 Google 的驗證要求基準 URI。
以下是這類文件的範例;欄位名稱是在 OpenID Connect Discovery 1.0 中指定 (如需欄位名稱的意義,請參閱該文件)。這些值僅供說明,可能會有所變更,但都是從最新版的實際 Google 導覽文件複製而來:
{ "issuer": "https://accounts.google.com", "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth", "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code", "token_endpoint": "https://oauth2.googleapis.com/token", "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo", "revocation_endpoint": "https://oauth2.googleapis.com/revoke", "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs", "response_types_supported": [ "code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token", "none" ], "subject_types_supported": [ "public" ], "id_token_signing_alg_values_supported": [ "RS256" ], "scopes_supported": [ "openid", "email", "profile" ], "token_endpoint_auth_methods_supported": [ "client_secret_post", "client_secret_basic" ], "claims_supported": [ "aud", "email", "email_verified", "exp", "family_name", "given_name", "iat", "iss", "locale", "name", "picture", "sub" ], "code_challenge_methods_supported": [ "plain", "S256" ] }
您可以快取探索文件中的值,避免 HTTP 往返。系統會使用標準 HTTP 快取標頭,因此請務必遵守相關規定。
用戶端程式庫
下列用戶端程式庫與常見架構整合,可簡化 OAuth 2.0 的實作程序:
符合 OpenID Connect 規範
Google 的 OAuth 2.0 驗證系統支援 OpenID Connect Core 規格的必要功能。任何設計與 OpenID Connect 搭配使用的用戶端,都應能與這項服務互通 (OpenID 要求物件除外)。
