OpenID Connect

Google 的 OAuth 2.0 API 可用於驗證與授權。本文件除了說明符合 OpenID Connect 規格的 OAuth 2.0 驗證作業,也已通過 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 的存取權。

To view the client ID and client secret for a given OAuth 2.0 credential, click the following text: Select credential. In the window that opens, choose your project and the credential you want, then click View.

Or, view your client ID and client secret from the Credentials page in API Console:

  1. Go to the Credentials page.
  2. Click the name of your credential or the pencil () icon. Your client ID and secret are at the top of the page.

設定重新導向 URI

您在 API Console 中設定的重新導向 URI 會決定 Google 將回應傳送至驗證要求的位置。

To create, view, or edit the redirect URIs for a given OAuth 2.0 credential, do the following:

  1. Go to the Credentials page.
  2. In the OAuth 2.0 client IDs section of the page, click a credential.
  3. View or edit the redirect URIs.

If there is no OAuth 2.0 client IDs section on the Credentials page, then your project has no OAuth credentials. To create one, click Create credentials.

自訂使用者同意畫面

對使用者來說,OAuth 2.0 驗證體驗包含同意畫面,當中說明使用者發布的資訊和適用的條款。舉例來說,當使用者登入時,系統可能會要求使用者授予電子郵件地址和基本帳戶資訊的存取權。請使用 scope 參數來要求這項資訊,您的應用程式可透過其驗證要求加入此參數。您也可以透過範圍要求取得其他 Google API 的存取權。

使用者同意畫面還會顯示品牌宣傳資訊,例如產品名稱、標誌和首頁網址。您可以在 API Console中控製品牌宣傳資訊。

要啟用項目的同意屏幕:

  1. Consent Screen page中打開Google API Console 。
  2. If prompted, select a project, or create a new one.
  3. 填寫表格,然後點擊保存

以下同意聲明對話方塊會顯示要求中合併 OAuth 2.0 和 Google 雲端硬碟範圍時,使用者會看到的內容。(也就是使用 Google OAuth 2.0 Playground 產生這個一般對話方塊,因此不含在 API Console中設定的品牌宣傳資訊)。

同意頁面螢幕截圖

存取服務

Google 和第三方提供的程式庫可協助處理各種實作驗證作業,以及驗證 Google API 的存取權。範例包括 Google Identity 服務Google 用戶端程式庫,適用於多種平台。

如果您選擇不要使用程式庫,請按照本文其餘部分的操作說明,針對可用的程式庫提供 HTTP 要求流程。

驗證使用者

驗證使用者包括取得 ID 權杖並進行驗證。ID 權杖OpenID Connect 的標準功能,用於在網際網路上分享身分宣告。

最常用來驗證使用者及取得 ID 權杖的方法,稱為「伺服器」流程和「隱含」流程。伺服器流程可讓應用程式的後端伺服器透過瀏覽器或行動裝置驗證使用者身分。當用戶端應用程式 (通常是在瀏覽器中執行的 JavaScript 應用程式) 需要直接存取 API 而不是透過後端伺服器存取時,就會使用隱含流程。

本文說明如何驗證伺服器流程以驗證使用者。隱含流程明顯複雜,因為安全性在用戶端處理及使用權杖時會面臨安全性風險。如果您需要執行隱含流程,我們強烈建議使用 Google Identity 服務

伺服器流程

請務必在 API Console中設定應用程式,讓應用程式採用這些通訊協定並驗證使用者。當使用者嘗試使用 Google 帳戶登入時,您必須:

  1. 建立反偽造狀態權杖
  2. 傳送驗證要求給 Google
  3. 確認反偽造狀態權杖
  4. 交換 code 以存取存取權杖和 ID 權杖
  5. 從 ID 權杖取得使用者資訊
  6. 驗證使用者

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 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//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 (選用)

只有在驗證要求中將 access_type 參數設為 offline 時,系統才會顯示這個欄位。 詳情請參閱「更新權杖」。

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 時間 (整數秒) 表示。
iat 一律 ID 權杖的核發時間。以 Unix 時間 (整數秒) 表示。
iss 一律 回應核發者的核發者 ID。Google ID 權杖一律必須是 https://accounts.google.comaccounts.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 範圍值時才會提供。
email_verified 如果使用者的電子郵件地址已通過驗證,則為 True,否則傳回 false。
family_name 使用者的姓氏或姓氏。會在有 name 版權聲明時提供。
given_name 使用者的姓名或名字。會在有 name 版權聲明時提供。
hd 與使用者 Google Cloud 機構相關聯的網域。只有在使用者屬於 Google Cloud 機構時才會提供。
locale 使用者語言代碼,以 BCP 47 語言標記表示。存在 name 憑證時,可能會提供。
name 完整顯示的使用者全名。可能會出現下列情況:
  • 要求範圍包含「profile」字串
  • 系統會透過權杖重新整理傳回 ID 權杖

如有 name 憑證時,可以使用這些憑證更新應用程式的使用者記錄。請注意,此版權聲明不保證一定會存在。

nonce 應用程式在驗證要求中提供的 nonce 值。您應確保該程序只會出現一次,藉此防範重播攻擊。
picture 使用者個人資料相片的網址。可能會出現下列情況:
  • 要求範圍包含「profile」字串
  • 系統會透過權杖重新整理傳回 ID 權杖

如有 picture 憑證時,可以使用這些憑證更新應用程式的使用者記錄。請注意,此版權聲明不保證一定會存在。

profile 使用者個人資料頁面的網址。可能會出現下列情況:
  • 要求範圍包含「profile」字串
  • 系統會透過權杖重新整理傳回 ID 權杖

如有 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 (必填) 您從 API Console Credentials page取得的用戶端 ID 字串,如取得 OAuth 2.0 憑證中所述。
nonce (必填) 應用程式產生的隨機值,啟用重播防護功能。
response_type (必填) 如果值為 code,請啟動基本授權碼流程,要求提供 POST 至權杖端點以取得權杖。如果值為 token id_tokenid_token token,則會啟動 Implicit 流程,要求重新導向 URI 使用 JavaScript 從 URI #fragment ID 擷取權杖。
redirect_uri (必填) 決定回應的傳送目的地。這個參數的值必須與您在 API Console Credentials page 中設定的其中一個授權重新導向值完全一致(包括 HTTP 或 HTTPS 配置、大小寫和結尾的「/」)。
scope (必填)

範圍參數的開頭必須是 openid 值,然後包含 profile 值和/或 email 值。

如果有 profile 範圍值,ID 權杖可能會 (但不保證一定) 包含使用者的預設 profile 憑證附加資訊。

如果有 email 範圍值,ID 權杖就會包含 emailemail_verified 憑證附加資訊。

除了這些 OpenID 專屬範圍外,範圍引數也可以包含其他範圍值。所有範圍值都必須以空格分隔,舉例來說,如要讓每個檔案的 Google 雲端硬碟檔案各自可存取,範圍參數可以是 openid profile email https://www.googleapis.com/auth/drive.file

如要瞭解可用範圍,請參閱 Google API 的 OAuth 2.0 範圍,或您要使用的 Google API 說明文件。

state (選用,但強烈建議使用)

通訊協定中四捨五入的不透明字串,也就是在基本流程的 URI 參數和隱式流程中,將 URI #fragment ID 傳回。

state 可用於關聯要求和回應。由於可以猜測 redirect_uri,因此使用 state 值可以提高傳入連線是應用程式啟動的驗證要求的結果。如果您產生隨機字串或針對部分 state 變數 (例如 Cookie) 進行編碼,就可以驗證回應,以確保該要求和回應是來自同一個瀏覽器。這可防範跨網站偽造要求等攻擊。

access_type (選填) 可以使用的值為 offlineonline。「離線存取」會註明效果。如果您要求存取權杖,除非指定 offline 的值,否則用戶端不會收到更新權杖。
display (選填) 指定授權伺服器顯示驗證和同意聲明使用者介面頁面的 ASCII 字串值。Google 伺服器已指定並接受下列值,但不會影響其行為:pagepopuptouchwap
hd (選填)

簡化 Google Cloud 機構擁有的帳戶登入程序。加入 Google Cloud 機構網域 (例如 mycollege.edu) 後,即可表明該網域的帳戶 UI 應針對該網域的帳戶進行最佳化。如要針對 Google Cloud 機構帳戶進行最佳化調整,而不只是一個 Google Cloud 機構網域,請設定星號值 (*):hd=*

請勿仰賴此使用者介面最佳化來控制可存取您應用程式的使用者,因為用戶端要求可以修改。請務必驗證傳回的 ID 權杖具有 hd 憑證值,例如與 mycolledge.edu 一樣。hd

include_granted_scopes (選填) 如果為 true 提供這個參數,且已授予授權要求,則授權就會包含先前授予這個使用者/應用程式組合的所有授權,請參閱遞增授權

請注意,您無法在「已安裝的應用程式」流程中進行漸進式授權。

login_hint (選填) 如應用程式知道要驗證的使用者,就可以提供這個參數做為驗證伺服器的提示。如果傳遞這項提示,系統會略過帳戶選擇工具,在登入表單中預先填入電子郵件方塊,或是選取適當的工作階段 (如果使用者使用多帳戶登入功能,避免應用程式登入錯誤的使用者發生問題)。值可以是電子郵件地址或 sub 字串,相當於使用者的 Google ID。
prompt (選填) 以空格分隔的字串值清單,指定授權伺服器提示使用者進行重新驗證和同意聲明。可能的值包括:
  • none

    授權伺服器不會顯示任何驗證或使用者同意畫面;如果使用者尚未通過驗證,且未針對要求範圍預先提供同意聲明,系統就會傳回錯誤。您可以使用 none 檢查現有的驗證和/或同意聲明。

  • consent

    授權伺服器在傳回資訊給用戶端之前,系統會先要求使用者同意。

  • select_account

    授權伺服器會提示使用者選取使用者帳戶。這樣一來,在授權伺服器中擁有多個帳戶的帳戶,就能選取多個目前具備工作階段的帳戶。

如未指定值,且使用者先前未獲授權,則使用者會看到同意畫面。

驗證 ID 權杖

除非你知道這些憑證直接來自 Google,否則你必須驗證伺服器上的所有 ID 權杖。例如,您的伺服器必須驗證從用戶端應用程式收到的任何 ID 權杖。

以下列舉幾個傳送 ID 權杖給伺服器的常見原因:

  • 傳送需要驗證的要求中的 ID 權杖。ID 權杖會指出提出要求的特定使用者,以及該 ID 權杖是由哪個用戶端授予。

ID 權杖具有機密性,如果攔截的話,可能會被濫用。請務必確保這些權杖只透過 HTTPS 傳輸,且只能透過 POST 資料或要求標頭傳輸。如果將 ID 權杖儲存在伺服器上,也必須安全地儲存。

讓 ID 權杖相當實用的一點是,您可以將這些憑證傳遞給應用程式的不同元件。這些元件可以使用 ID 權杖做為用來驗證應用程式和使用者的輕量驗證機制。但是,您「必須」進行驗證,才能使用 ID 權杖中的資訊或做為使用者已驗證時的斷言。

驗證 ID 權杖需要完成幾個步驟:

  1. 確認核發機構已正確簽署 ID 權杖。Google 核發的權杖會使用在探索文件 jwks_uri 中繼資料值中指定的 URI 簽署。
  2. 確認 ID 權杖中的 iss 憑證值等於 https://accounts.google.comaccounts.google.com
  3. 確認 ID 權杖中的 aud 憑證值等於應用程式用戶端 ID。
  4. 確認 ID 權杖的到期時間 (exp 個憑證) 尚未經過。
  5. 如果您在要求中指定 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 回應的快取指令來快取這些金鑰;在大部分情況下,Google 會使用 tokeninfo 端點以更有效率的方式執行本機驗證。這項驗證作業需要擷取並剖析憑證,並發出適當的加密編譯呼叫以檢查簽章。幸運的是,各種語言都能妥善進行偵錯的程式庫都能用來達成此目標 (請參閱 jwt.io)。

取得使用者個人資料

如要取得使用者的設定檔的其他相關資訊,您可以使用存取權杖 (也就是應用程式在驗證流程時接收的權杖) 和 OpenID Connect 標準:

  1. 為符合 OpenID 規定,您必須在驗證要求中加入 openid profile 範圍值。

    如要加入使用者的電子郵件地址,您可以指定額外的範圍值 email。如要同時指定 profileemail,您可以在驗證要求 URI 中加入下列參數:

    scope=openid%20profile%20email
  2. 將存取權杖新增至授權標頭,並向使用者資訊端點發出 HTTPS GET 要求。您必須使用 userinfo_endpoint 中繼資料值,從探索文件擷取該憑證。使用者資訊回應中包含使用者相關資訊,如 OpenID Connect Standard Claims 和「探索」文件的 claims_supported 中繼資料值所示。使用者或其機構可能會選擇提供或保留特定欄位,因此不一定是針對授權範圍的每個欄位提供資訊。

探索文件

OpenID Connect 通訊協定會使用多個端點來驗證使用者,以及要求取得權杖、使用者資訊和公開金鑰等資源。

為了簡化導入作業並提升彈性,OpenID Connect 可以使用「探索文件」,也就是位於已知位置的鍵/值組合,其中提供 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 探索 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 要求物件除外)。