OpenID Connect

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

Google 的 OAuth 2.0 API 可用於驗證作業和授權作業。本文件說明用於驗證的 OAuth 2.0 實作,並遵循 OpenID Connect 規格,並已獲得 OpenID 認證。此外,「使用 OAuth 2.0 存取 Google API」一文中列出的說明文件也適用於這項服務。如果您想以互動方式探索這個通訊協定,建議您使用 Google OAuth 2.0 Playground。 如需 Stack Overflow 說明,請使用「##39;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 將回應傳送至驗證要求的位置。

要創建,查看或編輯給定OAuth 2.0憑據的重定向URI,請執行以下操作:

  1. Go to the Credentials page.
  2. 在頁面的OAuth 2.0客戶端ID部分中,點擊一個憑據。
  3. 查看或編輯重定向URI。

如果“憑據”頁面上沒有OAuth 2.0客戶端ID部分,則您的項目沒有OAuth憑據。要創建一個,點擊創建憑證

自訂使用者同意畫面

對使用者而言,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. 交換存取權杖和 ID 權杖的 code
  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 ConsoleCredentials 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 ConsoleCredentials page取得的用戶端 ID,如取得 OAuth 2.0 憑證中所述。
client_secret 從 API ConsoleCredentials page取得的用戶端密鑰,如取得 OAuth 2.0 憑證中所述。
redirect_uri API ConsoleCredentials 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 以全名顯示的使用者全名。可能會出現下列情況:
  • 要求範圍包含字串「quot;」
  • ID 權杖已從權杖重新整理時傳回

如果有 name 憑證附加資訊,您可以使用這些憑證來更新應用程式的使用者記錄。請注意,本聲明不保證一定會顯示。

nonce 您的應用程式在驗證要求中提供的 nonce 值。您應確保只會提供一次,避免強制執行重播攻擊。
picture 使用者個人資料相片的網址。可能會出現下列情況:
  • 要求範圍包含字串「quot;」
  • ID 權杖已從權杖重新整理時傳回

如果有 picture 憑證附加資訊,您可以使用這些憑證來更新應用程式的使用者記錄。請注意,本聲明不保證一定會顯示。

profile 使用者設定檔頁面的網址。可能會出現下列情況:
  • 要求範圍包含字串「quot;」
  • ID 權杖已從權杖重新整理時傳回

如果有 profile 憑證附加資訊,您可以使用這些憑證來更新應用程式的使用者記錄。請注意,本聲明不保證一定會顯示。

6. 驗證使用者

從 ID 權杖取得使用者資訊後,您應查詢應用程式的使用者資料庫。如果使用者在您的資料庫中已有使用者,且是由 Google API 回應符合所有登入規定時,您應該為該使用者啟動應用程式工作階段。

如果使用者資料庫中沒有使用者,請將使用者重新導向至新使用者的註冊流程。您可以根據自己從 Google 提供的資訊自動註冊使用者,或是至少在註冊表單中預先填入許多欄位。除了 ID 權杖中的資訊外,您還可以在使用者設定檔端點中找到額外的使用者個人資料資訊

進階主題

以下各節提供了 Google OAuth 2.0 API 的詳細說明。開發人員請注意,這些資訊均適用於驗證和授權方面的進階要求。

其他 Google API 的存取權

使用 OAuth 2.0 進行驗證的好處之一是,您的應用程式可以在驗證使用者的同時,代表使用者 (例如 YouTube、Google 雲端硬碟、日曆或聯絡人) 使用其他 Google API。如要這麼做,請在傳送給 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 ConsoleCredentials page取得的用戶端 ID 字串,如取得 OAuth 2.0 憑證中所述。
nonce (必填) 由應用程式產生的隨機值,會啟用重播保護功能。
response_type (必填) 如果值為 code,系統會啟動基本授權流程流程,要求透過 POST 向權杖端點取得權杖。如果值為 token id_tokenid_token token,就會啟動隱含流程,要求在重新導向 URI 中使用 JavaScript 從 URI #fragment ID 擷取權杖。
redirect_uri (必填) 決定回應的傳送位置。這個參數的值必須與您在 API ConsoleCredentials 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 值可以確保傳入連線是應用程式發出的驗證要求產生的結果。如果您產生隨機字串,或將此用戶端狀態的雜湊 (例如 Cookie) 編碼成此瀏覽器 state,就可以進一步驗證回應,確保要求和回應來自同一個瀏覽器。這種做法可以防範跨網站要求偽造等攻擊。

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

簡化 Google Cloud 機構所擁有帳戶的登入程序。加入 Google Cloud 機構網域 (例如 mycollege.edu),您可以表明已針對這些網域的帳戶最佳化帳戶選取 UI。一般來說,如要針對 Google Cloud 機構帳戶進行最佳化,而不只是一個 Google Cloud 機構網域,請設定星號 (*):hd=*

請勿仰賴此 UI 最佳化功能來控制誰能夠存取您的應用程式,因為用戶端要求可以修改。請務必驗證傳回的 ID 權杖hd 版權聲明值符合預期 (例如 mycolledge.edu)。與要求參數不同,ID 權杖 hd 憑證附加在 Google 的安全性權杖內,因此值得信任。

include_granted_scopes (選填) 如果這項參數的值為 true,且已獲授權,授權就會包含其他先前針對使用者/應用程式組合授予的其他範圍授權。請參閱逐步授權

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

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

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

  • consent

    授權伺服器會在將資訊傳回用戶端前,提示使用者提供同意聲明。

  • select_account

    授權伺服器會提示使用者選取使用者帳戶。這個做法可讓授權伺服器擁有多個帳戶的使用者從目前工作階段選取的多個帳戶中選取一個。

如未指定任何值,且使用者先前並未授權存取,則系統會顯示同意畫面。

驗證 ID 權杖

除非您知道 Google 的權杖是否直接來自 Google ,否則您必須驗證伺服器中的所有 ID 權杖。舉例來說,您的伺服器必須從用戶端應用程式收到的任何 ID 權杖進行驗證。

以下是您將 ID 權杖傳送至伺服器的常見原因:

  • 傳送需要驗證的要求的 ID 權杖。ID 權杖會指出提出要求的使用者和取得該 ID 權杖的用戶端。

ID 權杖屬於機密資訊,可能會在攔截時遭到濫用。請務必透過 HTTPS 和要求標頭或透過 POST 資料,只將權杖透過 HTTPS 傳輸,以安全的方式處理。如果您將 ID 憑證儲存在伺服器上,您也必須妥善儲存權杖。

ID 權杖的其中一項優點是,您可以在應用程式的不同元件之間傳送 ID。這些元件可以使用 ID 權杖做為驗證應用程式和使用者的輕量驗證機制。但是,您「必須」使用 ID 權杖中的資訊,或將其視為使用者已通過驗證的宣告。

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

  1. 確認核發機構已正確簽署身分證件。系統會使用探索文件 jwks_uri 中繼資料值中指定的 URI 找到其中一個憑證,以簽署 Google 核發的權杖。
  2. 確認 ID 權杖中的 iss 聲明值等於 https://accounts.google.comaccounts.google.com
  3. 確認 ID 權杖中的 aud 憑證值是否與應用程式的用戶端 ID 相同。
  4. 確認身分證件的到期時間 (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 回應的快取指令對金鑰進行快取,而且在多數情況下,使用 tokeninfo 端點更有效率地執行本機驗證。這項驗證需要擷取及剖析憑證,並發出適當的加密編譯呼叫來檢查簽名。幸好,我們提供多種語言版本的偵錯程式庫,支援多種語言,請參閱 jwt.io

取得使用者個人資料

如要取得其他使用者的其他設定檔資訊,您可以使用存取權杖 (應用程式在驗證流程期間收到的應用程式) 和 OpenID Connect 標準:

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

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

    scope=openid%20profile%20email
  2. 將存取權杖新增至授權標頭,並向 userinfo 端點發出 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 要求物件除外)。