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 的協助,請使用 &&33;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 登入Google 用戶端程式庫 (適用於多種平台)。

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

驗證使用者

驗證使用者需要取得 ID 憑證並加以驗證。ID 憑證OpenID Connect 的標準化功能,專門用於在網路上分享身分認證。

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

本文說明如何執行伺服器流程,以驗證使用者。由於用戶端在處理及使用用戶端的權杖時,安全性風險會比較明顯。如果您需要實作隱含流程,強烈建議您使用 Google 登入功能。

伺服器流程

您必須在 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 ConsoleCredentials 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 憑證前,請務必先完成「驗證」程序,之後您才能與 Google 直接通訊。此外,由於您是透過沒有中介的 HTTPS 管道直接與 Google 進行通訊,並透過用戶端密鑰向 Google 驗證自己的身分,因此您可以確定收到的符記確實來自 Google,而且有效。如果您的伺服器將 ID 憑證傳送至應用程式的其他元件,則其他元件必須先驗證憑證才能使用。

大部分的 API 程式庫會將驗證結合解碼的 Base64 網址編碼值,並在其中剖析 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 權杖可能包含下列欄位 (又稱為 claims):

領取 已提供 說明
aud 一律 這個 ID 權杖的目標對象。這必須是應用程式的 OAuth 2.0 用戶端 ID。
exp 一律 不接受到期日的到期日。以 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;profile」
  • ID 符記從更新憑證中傳回

如果有 name 聲明,您可以使用這些憑證更新應用程式的使用者記錄。請注意,我們不保證一定會顯示這項版權聲明。

nonce 您的應用程式在驗證要求中提供的 nonce 值。您應確保只會重複提出一次攻擊,以強制執行防止抵禦攻擊。
picture 使用者個人資料相片的網址。可能時機如下:
  • 要求範圍包含字串「quot;profile」
  • ID 符記從更新憑證中傳回

如果有 picture 聲明,您可以使用這些憑證更新應用程式的使用者記錄。請注意,我們不保證一定會顯示這項版權聲明。

profile 使用者的個人資料頁面網址。可能時機如下:
  • 要求範圍包含字串「quot;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 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),指明帳戶選擇的使用者介面應該針對該網域的帳戶進行最佳化。一般來說,如要針對 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,否則您必須驗證伺服器中的所有 ID 憑證。例如,您的伺服器必須驗證用戶端應用程式收到的任何 ID 憑證是否可證明為真實。

以下是傳送 ID 憑證至伺服器的常見情形:

  • 傳送需要驗證要求的 ID 憑證。ID 憑證會告訴發出要求的特定使用者,以及授予該 ID 憑證的用戶端。

ID 權杖屬於機密性質,如果遭到攔截,可能會誤用。請務必透過 HTTPS 傳輸這些要求,並且只透過 POST 資料或在要求標頭中妥善處理這些符記。如果您將 ID 憑證儲存在伺服器上,也必須將這些憑證安全地儲存在伺服器上。

ID 憑證的其中一項優點是,您可以將這類 ID 傳遞至應用程式的不同元件。這些元件可以使用 ID 憑證做為精簡的驗證機制,為應用程式和使用者進行驗證。不過,您「必須」使用這個 ID 權杖中的資訊,或將其做為使用者驗證的宣告,然後才能使用該憑證。

驗證身分證件時需完成幾個步驟:

  1. 確認核發單位是否正確簽署 ID 符記。使用探索文件jwks_uri 中繼資料值中指定的 URI 簽署 Google 核發的憑證。
  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 回應的快取指令來快取金鑰;在大多數情況下,使用本機驗證可更有效率地執行本機驗證,比使用 tokeninfo 端點更有效率。這項驗證作業需要擷取及剖析憑證,並對其進行適當的加密編譯呼叫來檢查簽名。幸好,我們提供多種語言的偵錯程式庫,支援多種語言,請參閱 jwt.io

取得使用者個人資料

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

  1. 為遵守 OpenID,您必須在驗證要求中加入 openid profile 範圍值。

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

    scope=openid%20profile%20email
  2. 將您的存取憑證新增至授權標頭,並向 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 探索 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 要求物件除外)。