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 API Console 中設定專案,才能取得 OAuth 2.0 憑證、設定重新導向 URI,以及 (選擇性) 自訂使用者在同意畫面上看到的品牌資訊,才能使用 Google 的 OAuth 2.0 驗證系統進行使用者登入。您也可以使用 API Console 建立服務帳戶、啟用計費功能、設定篩選功能,以及執行其他工作。詳情請參閱 Google API Console說明。
取得 OAuth 2.0 憑證
您需要使用 OAuth 2.0 憑證 (包括用戶端 ID 和用戶端密鑰) 來驗證使用者及取得 Google API 的存取權。
要查看给定OAuth 2.0凭据的客户端ID和客户端密钥,请单击以下文本: 选择凭据 。在打开的窗口中,选择您的项目和所需的凭证,然后单击“ 查看” 。
或者,从API Console的“ 凭据”页面中查看您的客户端ID和客户端密钥:
- Go to the Credentials page.
- 单击您的凭证名称或铅笔( create )图标。您的客户ID和密码位于页面顶部。
設定重新導向 URI
您在 API Console 中設定的重新導向 URI 會決定 Google 將回應傳送至驗證要求的位置。
要创建,查看或编辑给定OAuth 2.0凭据的重定向URI,请执行以下操作:
- Go to the Credentials page.
- 在页面的OAuth 2.0客户端ID部分中,点击一个凭据。
- 查看或编辑重定向URI。
如果“凭据”页面上没有OAuth 2.0客户端ID部分,则您的项目没有OAuth凭据。要创建一个,点击创建凭证 。
自訂使用者同意畫面
針對使用者,OAuth 2.0 驗證體驗包含同意畫面,其中說明使用者將發布的資訊以及適用的條款。例如,使用者登入時,系統可能會請使用者授予應用程式存取電子郵件地址和基本帳戶資訊的權限。您可以使用 scope
參數要求存取這項資訊,應用程式會在其驗證要求中加入該參數。您也可以使用範圍要求其他 Google API 的存取權。
使用者同意畫面也會顯示產品名稱、標誌和首頁網址等品牌資訊。你可以在 API Console中控管品牌資訊。
要啟用項目的同意屏幕:
- 在Consent Screen page中打開Google API Console 。
- If prompted, select a project, or create a new one.
- 填寫表格,然後點擊保存 。
在下列同意聲明對話方塊中,顯示要求中同時包含 OAuth 2.0 和 Google 雲端硬碟範圍時,使用者會看到的內容。(這個通用對話方塊是使用 Google OAuth 2.0 Playground 產生,因此不包含在 API Console中設定的品牌宣傳資訊)。
![同意聲明頁面螢幕截圖](https://developers.google.cn/static/identity/protocols/oauth2/images/examples/scope-authorization.png?authuser=3&hl=zh-tw)
存取服務
您可以透過 Google 和第三方提供的程式庫,處理許多驗證使用者及取得 Google API 存取權的實作詳細資料。例如 Google Identity 服務和 Google 用戶端程式庫,這些項目適用於各種平台。
如果您選擇不使用程式庫,請按照本文件其餘部分的操作說明,瞭解可用程式庫之下的 HTTP 要求流程。
驗證使用者
驗證使用者需要取得及驗證 ID 權杖。ID 權杖是 OpenID Connect 的標準化功能,可用來在網際網路上共用身分斷言。
最常用來驗證使用者及取得 ID 權杖的方法稱為「伺服器」流程和「隱含」流程。伺服器流程可讓應用程式的後端伺服器使用瀏覽器或行動裝置驗證個人身分。當用戶端應用程式 (通常是在瀏覽器中執行的 JavaScript 應用程式) 需要直接透過後端伺服器存取 API 時,就會使用隱含流程。
本文件說明如何執行伺服器流程以驗證使用者。由於在用戶端處理及使用權杖時存在安全性風險,隱含流程更為複雜。如果您需要實作隱含流程,強烈建議您使用 Google Identity 服務。
伺服器流程
請務必在 API Console中設定應用程式,讓應用程式可以使用這些通訊協定並驗證使用者。當使用者嘗試使用 Google 帳戶登入時,您必須:
1. 建立反偽造狀態權杖
您必須防止要求偽造攻擊,保障使用者的安全。第一步是建立不重複的工作階段符記,這個符記可保留應用程式和使用者用戶端之間的狀態。您稍後會將這個不重複的工作階段憑證與 Google OAuth 登入服務傳回的驗證回應進行比對,藉此驗證使用者是提出要求,而非惡意攻擊者。這類權杖通常稱為跨網站要求偽造權杖 (CSRF)。
使用高品質隨機號碼產生器建構的字串 (長度為 30 以上),是狀態權杖的絕佳選擇。另一個則是使用在後端保留密鑰的金鑰簽署部分工作階段狀態變數,藉此產生的雜湊。
以下程式碼示範如何產生不重複的工作階段符記。
PHP
您必須下載 PHP 適用的 Google API 用戶端程式庫,才能使用這個範例。
// 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
您必須下載 Python 適用的 Google API 用戶端程式庫,才能使用這個範例。
# 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
,您從 API Console Credentials page取得。response_type
,在基本授權碼流程要求中應為code
。(詳情請參閱response_type
)。scope
,在基本要求中應為openid email
。(詳情請參閱scope
)。redirect_uri
應為在接收 Google 回應的伺服器中 HTTP 端點。這個值必須與您在 API Console Credentials page中設定的 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 範例, 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//oauth2.example.com/code& 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://oauth2.example.com/code?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
在伺服器上,您必須確認 Google 收到的 state
與您在步驟 1 中建立的工作階段符記。這項來回驗證有助於確保使用者 (而非惡意指令碼) 確實提出要求。
以下程式碼示範如何確認您在步驟 1 建立的工作階段符記:
PHP
您必須下載 PHP 適用的 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->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
您必須下載 Python 適用的 Google API 用戶端程式庫,才能使用這個範例。
# 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 |
您從 API Console Credentials page取得的用戶端 ID,如取得 OAuth 2.0 憑證中所述。 |
client_secret |
您從 API Console Credentials page取得的用戶端密鑰,如取得 OAuth 2.0 憑證中所述。 |
redirect_uri |
為 API Console
Credentials page中指定的指定 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//oauth2.example.com/code& 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 權杖才能使用該權杖。不過,由於您是直接與 Google 通訊,且希望透過不含中介的 HTTPS 管道與 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 時間 (整數秒) 表示。 |
iat |
一律 | ID 權杖的核發時間。以 Unix 時間 (整數秒) 表示。 |
iss |
一律 | 回應核發者的核發者 ID。Google ID 權杖一律為 https://accounts.google.com 或 accounts.google.com 。 |
sub |
一律 | 使用者的專屬 ID,必須專屬於所有 Google 帳戶,且不得重複使用。Google 帳戶可在不同時間點使用多個電子郵件地址,但 sub 值一律不會變更。在應用程式中使用 sub 做為使用者的專屬 ID 金鑰。長度上限為 255 個區分大小寫的 ASCII 字元。 |
at_hash |
存取權杖雜湊。提供存取權杖已綁定識別權杖的驗證。如果在伺服器流程中使用 access_token 值核發 ID 權杖,則一律會包含這個憑證附加資訊。這項憑證聲明可做為替代機制,藉此防範跨網站偽造攻擊,但如果您按照步驟 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 日曆或 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 |
(必填) | 您從 API Console Credentials page取得的用戶端 ID 字串,如取得 OAuth 2.0 憑證中所述。 |
nonce |
(必填) | 應用程式產生的隨機值,用於啟用重播保護功能。 |
response_type |
(必填) | 如果值為 code ,請啟動基本授權碼流程,要求 POST 對權杖端點取得權杖。如果值為 token id_token 或 id_token token ,請啟動隱含流程,要求在重新導向 URI 中使用 JavaScript,以便從 URI #fragment ID 擷取權杖。 |
redirect_uri |
(必填) | 決定回應傳送的位置。這個參數的值必須與您在 API Console Credentials page 中設定的其中一個授權重新導向值 (包括 HTTP 或 HTTPS 配置、大小寫,以及結尾 (如有)) 完全相符。 |
scope |
(必填) | 範圍參數的開頭必須是 如果有 如果有 除了這些 OpenID 專屬範圍外,範圍引數也可以包含其他範圍值。所有範圍值皆須以空格分隔。舉例來說,如果您想讓每個檔案都存取使用者的 Google 雲端硬碟,範圍參數可能是 如要瞭解可用範圍,請參閱 Google API 的 OAuth 2.0 範圍,或您要使用的 Google API 的說明文件。 |
state |
(選用,但強烈建議使用) | 會在通訊協定中往返的不透明字串;也就是說,這個字串會在基本流程中做為 URI 參數傳回,並在隱式流程中的 URI
|
access_type |
(選填) | 允許的值為 offline 和 online 。效果會記錄在「離線存取」頁面中。如果您要求存取權杖,則除非指定 offline 值,否則用戶端不會收到更新權杖。 |
display |
(選填) | ASCII 字串值,用於指定授權伺服器如何顯示驗證和同意聲明使用者介面頁面。下列值是由 Google 伺服器指定並接受,但對其行為沒有任何影響:page 、popup 、touch 和 wap 。 |
hd |
(選填) | 簡化 Google Cloud 機構所擁有帳戶的登入程序。您可以加入 Google Cloud 機構網域 (例如 mycollege.edu),藉此表明應針對該網域中的帳戶,將帳戶選擇 UI 最佳化。如要針對 Google Cloud 機構帳戶 (而非只針對一個 Google Cloud 機構網域) 進行最佳化調整,請設定星號 ( 請勿仰賴這項 UI 最佳化來控制誰能存取您的應用程式,因為用戶端要求可以修改。請務必validate傳回的 ID 權杖,其 |
include_granted_scopes |
(選填) | 如果這項參數提供 true 值,且系統授予授權要求,則授權會包含先前針對其他範圍授予這個使用者/應用程式組合的任何授權。請參閱「增量授權」。請注意,您無法在「安裝式應用程式」流程中執行增量授權。 |
login_hint |
(選填) | 當應用程式知道要驗證的使用者為何,便可提供此參數給驗證伺服器提示。傳遞這項提示後,帳戶選擇工具將隱藏帳戶選擇工具,並在登入表單中預先填入電子郵件方塊;如果是由使用者使用多帳戶登入功能,則可選取適當的工作階段,避免應用程式記錄錯誤。這個值可以是電子郵件地址或 sub 字串,相當於使用者的 Google ID。 |
prompt |
(選填) | 以空格分隔的字串值清單,指定授權伺服器是否提示使用者重新驗證及同意。可能的值包括:
如未指定任何值,且使用者先前未獲得授權,系統會顯示同意畫面。 |
驗證 ID 權杖
您必須在伺服器上驗證所有 ID 權杖,除非您確定這些權杖直接來自 Google。舉例來說,您的伺服器必須驗證從用戶端應用程式接收的任何 ID 權杖是否真實。
以下是將 ID 權杖傳送至伺服器的常見情況:
- 透過需要通過驗證的要求傳送 ID 權杖。ID 權杖可讓您瞭解發出要求的特定使用者,以及為哪個用戶端授予 ID 權杖。
ID 權杖屬於機密資訊,如果遭到攔截,可能會遭到濫用。您必須確保這些權杖僅透過 HTTPS 傳輸,並且僅透過 POST 資料或要求標頭,才能以安全的方式處理。如果您將 ID 權杖儲存在伺服器上,也必須妥善保存。
ID 權杖很實用,因為您可以傳遞應用程式的不同元件。這些元件可將 ID 權杖做為驗證應用程式和使用者的輕量驗證機制。但是,您必須先驗證 ID 權杖,才能使用 ID 權杖中的資訊,或將其當做使用者已驗證的斷言。
驗證 ID 權杖需要幾個步驟:
- 驗證核發機構是否正確簽署 ID 權杖。Google 核發的權杖是使用探索文件
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
解除參照。如果權杖簽章有效,回應將會是其解碼 JSON 物件表單中的 JWT 酬載。
tokeninfo
端點適合用於偵錯,但如果是實際工作環境,請從金鑰端點擷取 Google 公開金鑰,並在本機執行驗證。您應使用 jwks_uri
中繼資料值,從探索文件擷取金鑰 URI。向偵錯端點發出的要求可能會經過節流或出現間歇錯誤。
由於 Google 不常變更公開金鑰,因此您可以使用 HTTP 回應的快取指令來快取這類金鑰,在大多數情況下,比起使用 tokeninfo
端點,執行本機驗證的效率更高。這項驗證程序需要擷取並剖析憑證,並進行適當的加密編譯呼叫來檢查簽名。幸好,有許多語言經過完善偵錯的程式庫可達成這個目標 (請參閱 jwt.io)。
取得使用者個人資料
如要取得使用者的其他設定檔資訊,您可以使用存取權杖 (應用程式在驗證流程期間接收) 和 OpenID Connect 標準:
為符合 OpenID 規範,您必須在驗證要求中加入
openid profile
範圍值。如要納入使用者的電子郵件地址,您可以指定
email
的額外範圍值。如要同時指定profile
和email
,您可以在驗證要求 URI 中加入下列參數:scope=openid%20profile%20email
- 將您的存取權杖新增至授權標頭,並向 userinfo 端點發出 HTTPS
GET
要求,則您應使用userinfo_endpoint
中繼資料值,從探索文件擷取該端點。userinfo 回應包含使用者相關資訊,如OpenID Connect Standard Claims
和探索文件的claims_supported
中繼資料值所述。使用者或其機構可能會選擇提供或保留特定欄位,因此可能無法針對已授權存取範圍的每個欄位取得資訊。
「探索」文件
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 Discovery 文件的最新版本複製而來:
{ "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 要求物件除外)。