使用 OAuth 連結 Google 帳戶

帳戶連結使用業界標準 OAuth 2.0 隱含授權碼流程。您的服務必須支援符合 OAuth 2.0 規定的授權憑證交換端點。

在「暗示」流程中,Google 會在使用者的瀏覽器中開啟您的授權端點。成功登入後,會將長期存取憑證傳回 Google。目前從 Google 發出的每個要求都會包含這個存取憑證。

在「授權碼」流程中,您需要兩個端點:

  • Authorization 端點,可為尚未登入的使用者顯示登入 UI。授權端點也會建立短期的授權碼來記錄使用者。同意要求的存取權。

  • 憑證交換端點,該端點負責兩種交換類型:

    1. 將授權碼提供給長期使用憑證和短期存取憑證。當使用者完成帳戶連結流程時,系統就會執行這個交換作業。
    2. 針對短期存取權杖交換長期更新權杖。 如果 Google 需要這個存取憑證過期,因此需要進行這個交換作業。

選擇 OAuth 2.0 流程

雖然隱含流程比較簡單,但 Google 建議採用隱含流程所核發的存取憑證永遠不會過期。這是因為憑證在隱含流程到期後,必須強制重新連結帳戶。如果您需要基於安全考量而要求憑證過期,強烈建議您改用授權碼流程。

設計指南

本節說明您針對 OAuth 連結流程託管的使用者畫面設計要求和建議。在 Google 應用程式呼叫 API 後,您的平台會向使用者顯示登入 Google 頁面和帳戶連結同意畫面。使用者同意連結帳戶之後,系統就會將他們重新導向 Google 的應用程式。

下圖顯示使用者將 Google 帳戶連結到驗證系統的步驟。第一個螢幕截圖顯示了使用者從平台啟動的連結。第二張圖片則顯示使用者登入 Google 的第三張圖片,第三張圖片則顯示使用者同意授權及確認將自己的 Google 帳戶連結至您的應用程式。最終螢幕截圖顯示 Google app 中成功連結的使用者帳戶。
圖 1.連結 Google 帳戶和同意畫面的帳戶連結。

必要條件

  1. 您必須通知使用者的帳戶將連結至 Google,而不是特定的 Google 產品,例如 Google Home 或 Google 助理。

建議

建議您採取下列做法:

  1. 顯示 Google 的隱私權政策。在同意畫面中加入 Google 隱私權政策連結。

  2. 要分享的資料。使用簡明扼要的用詞告訴使用者 Google 需要哪些資料,以及收集這些資料的原因。

  3. 加入明確的行動號召。在同意畫面上註明明確的行動號召 (例如「同意和連結」)。這是因為使用者必須瞭解需要與 Google 分享哪些資料,才能連結自己的帳戶。

  4. 取消功能:如果使用者選擇不要進行連結,可以提供取消或取消訂閱的方式。

  5. 清除登入程序。確保使用者明確能登入 Google 帳戶,例如使用者名稱和密碼欄位或使用 Google 帳戶登入欄位。

  6. 取消連結。提供機制,讓使用者能取消連結,例如 您平台中帳戶設定的網址。您也可以加入 Google 帳戶連結,方便使用者管理已連結帳戶。

  7. 可變更使用者帳戶。建議使用者切換帳戶的方法。如果使用者經常擁有多個帳戶,這項功能就特別實用。

    • 如果使用者必須先關閉同意畫面才能切換帳戶,請將可復原的錯誤傳送給 Google,讓使用者可透過 OAuth 連結隱含流程登入所需帳戶。
  8. 加入您的標誌。在同意畫面中顯示公司標誌。 請善用樣式指南來放置標誌。如果您希望一併顯示 Google 的標誌,請參閱標誌和商標一文。

Create the project

To create your project to use account linking:

  1. Go to the Google API Console.
  2. 單擊創建項目
  3. 輸入名稱或接受生成的建議。
  4. 確認或編輯所有剩餘字段。
  5. 點擊創建

要查看您的項目ID:

  1. Go to the Google API Console.
  2. 在登錄頁面的表格中找到您的項目。項目ID出現在ID列中。

The Google Account Linking process includes a consent screen which tells users the application requesting access to their data, what kind of data they are asking for and the terms that apply. You will need to configure your OAuth consent screen before generating a Google API client ID.

  1. Open the OAuth consent screen page of the Google APIs console.
  2. If prompted, select the project you just created.
  3. On the "OAuth consent screen" page, fill out the form and click the “Save” button.

    Application name: The name of the application asking for consent. The name should accurately reflect your application and be consistent with the application name users see elsewhere. The application name will be shown on the Account Linking consent screen.

    Application logo: An image on the consent screen that will help users recognize your app. The logo is shown on Account linking consent screen and on account settings

    Support email: For users to contact you with questions about their consent.

    Scopes for Google APIs: Scopes allow your application to access your user's private Google data. For the Google Account Linking use case, default scope (email, profile, openid) is sufficient, you don’t need to add any sensitive scopes. It is generally a best practice to request scopes incrementally, at the time access is required, rather than up front. Learn more.

    Authorized domains: To protect you and your users, Google only allows applications that authenticate using OAuth to use Authorized Domains. Your applications' links must be hosted on Authorized Domains. Learn more.

    Application Homepage link: Home page for your application. Must be hosted on an Authorized Domain.

    Application Privacy Policy link: Shown on Google Account Linking consent screen. Must be hosted on an Authorized Domain.

    Application Terms of Service link (Optional): Must be hosted on an Authorized Domain.

    Figure 1. Google Account Linking Consent Screen for a fictitious Application, Tunery

  4. Check "Verification Status", if your application needs verification then click the "Submit For Verification" button to submit your application for verification. Refer to OAuth verification requirements for details.

實作 OAuth 伺服器

授權碼流的的OAuth 2.0服務器實現由兩個端點,通過HTTPS,你的服務使可用的。第一個端點是授權端點,它負責查找或獲得用戶對數據訪問的同意。授權端點向尚未登錄的用戶顯示登錄 UI,並記錄對請求訪問的同意。第二個端點是令牌交換端點,用於獲取加密字符串,稱為令牌,授權用戶訪問您的服務。

當 Google 應用程序需要調用您的服務的某個 API 時,Google 會結合使用這些端點來獲得您的用戶的許可,以代表他們調用這些 API。

Google發起的一次OAuth 2.0授權碼流會話流程如下:

  1. Google 在用戶的瀏覽器中打開您的授權端點。如果流程在 Action 的純語音設備上開始,Google 會將執行轉移到手機。
  2. 用戶登錄(如果尚未登錄)並授予 Google 使用您的 API 訪問其數據的權限(如果他們尚未授予權限)。
  3. 您的服務創建一個授權碼,並返回給谷歌。為此,請將用戶的瀏覽器重定向回 Google,並將授權代碼附加到請求中。
  4. 谷歌發送授權代碼,您的令牌交換終結,從而驗證代碼的真實性,並返回一個訪問令牌刷新令牌。訪問令牌是一個短期令牌,您的服務接受它作為訪問 API 的憑據。刷新令牌是一個長期存在的令牌,Google 可以存儲它並在它們到期時使用它來獲取新的訪問令牌。
  5. 用戶完成帳戶關聯流程後,從 Google 發送的每個後續請求都包含一個訪問令牌。

處理授權請求

當您需要使用 OAuth 2.0 授權代碼流執行帳戶關聯時,Google 會將用戶發送到您的授權端點,並發送一個包含以下參數的請求:

授權端點參數
client_id您分配給 Google 的客戶 ID。
redirect_uri您向其發送對此請求的響應的 URL。
state傳遞回 Google 的簿記值在重定向 URI 中保持不變。
scope可選:以空格分隔的集合,其指定谷歌正在請求授權的數據範圍的字符串。
response_type要在響應中返回的值的類型。對於的OAuth 2.0授權碼流,響應類型總是code
user_locale在谷歌帳戶語言設置RFC5646格式,用於本地化用戶的首選語言內容。

例如,如果您的授權端點可在https://myservice.example.com/auth ,請求看起來像下面這樣:

GET https://myservice.example.com/auth?client_id=GOOGLE_CLIENT_ID&redirect_uri=REDIRECT_URI&state=STATE_STRING&scope=REQUESTED_SCOPES&response_type=code&user_locale=LOCALE

對於處理登錄請求的授權端點,請執行以下步驟:

  1. 驗證client_id您分配給谷歌的客戶ID匹配,並且該redirect_uri由谷歌為您服務提供的重定向URL匹配。這些檢查對於防止授予對意外或配置錯誤的客戶端應用程序的訪問權限非常重要。如果你支持多種OAuth 2.0流程的,也確認response_typecode
  2. 檢查用戶是否已登錄您的服務。如果用戶未登錄,請完成服務的登錄或註冊流程。
  3. 生成供 Google 用於訪問您的 API 的授權代碼。授權碼可以是任何字符串值,但必須唯一代表用戶、token所針對的客戶端、授權碼的過期時間,並且不能被猜到。您通常會發出大約 10 分鐘後過期的授權代碼。
  4. 確認URL指定由redirect_uri參數有以下形式:
      https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID
      https://oauth-redirect-sandbox.googleusercontent.com/r/YOUR_PROJECT_ID
      
  5. 重定向用戶的瀏覽器由指定的URL redirect_uri參數。當你通過附加重定向包括剛剛生成授權碼和原始未修正的狀態值codestate參數。以下是所得的URL的一個示例:
    https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID?code=AUTHORIZATION_CODE&state=STATE_STRING

處理令牌交換請求

您的服務的令牌交換端點負責兩種令牌交換:

  • 交換訪問令牌和刷新令牌的授權代碼
  • 交換刷新令牌以獲取訪問令牌

令牌交換請求包括以下參數:

令牌交換端點參數
client_id將請求源標識為 Google 的字符串。此字符串必須在您的系統中註冊為 Google 的唯一標識符。
client_secret您在 Google 上為您的服務註冊的秘密字符串。
grant_type正在交換的令牌類型。這是不是authorization_coderefresh_token
codegrant_type=authorization_code ,這個參數是從您登錄或令牌交換終結收到谷歌的代碼。
redirect_urigrant_type=authorization_code ,該參數是在初始授權請求中使用的URL。
refresh_tokengrant_type=refresh_token ,這個參數是令牌從令牌交換終結收到谷歌的刷新。
交換訪問令牌和刷新令牌的授權代碼

在用戶登錄並且您的授權端點向 Google 返回一個短期授權代碼後,Google 會向您的令牌交換端點發送請求,以交換訪問令牌和刷新令牌的授權代碼。

對於這些請求,價值grant_typeauthorization_code ,和值code是您先前授予給谷歌授權碼的值。以下是為訪問令牌和刷新令牌交換授權代碼的請求示例:

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=REDIRECT_URI

要為訪問Exchange授權碼令牌和刷新令牌,您的令牌交換終結響應POST通過執行以下步驟要求:

  1. 驗證該client_id識別為授權原點,並且所述請求源client_secret預期值相匹配。
  2. 驗證授權碼是否有效且未過期,以及請求中指定的客戶端 ID 是否與與授權碼關聯的客戶端 ID 匹配。
  3. 確認URL中指定由redirect_uri參數是相同的初始授權請求中使用的值。
  4. 如果您無法驗證所有的上述標準,則返回一個HTTP 400錯誤的請求錯誤與{"error": "invalid_grant"}作為身體。
  5. 否則,使用授權代碼中的用戶 ID 生成刷新令牌和訪問令牌。這些令牌可以是任何字符串值,但它們必須唯一地代表令牌所針對的用戶和客戶端,並且不能被猜測。對於訪問令牌,還要記錄令牌的到期時間,通常是您發出令牌後的一個小時。刷新令牌不會過期。
  6. 返回以下JSON對象在HTTPS響應的主體:
    {
    "token_type": "Bearer",
    "access_token": "ACCESS_TOKEN",
    "refresh_token": "REFRESH_TOKEN",
    "expires_in": SECONDS_TO_EXPIRATION
    }
    

Google 為用戶存儲訪問令牌和刷新令牌,並記錄訪問令牌的到期時間。當訪問令牌過期時,Google 使用刷新令牌從您的令牌交換端點獲取新的訪問令牌。

交換刷新令牌以獲取訪問令牌

當訪問令牌過期時,Google 會向您的令牌交換端點發送請求,以將刷新令牌交換為新的訪問令牌。

對於這些請求,價值grant_typerefresh_token ,和值refresh_token是令牌先前授予谷歌刷新的值。以下是將刷新令牌交換為訪問令牌的請求示例:

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

要交換令牌的訪問令牌刷新,您的令牌交換終結響應POST通過執行以下步驟要求:

  1. 驗證client_id標識請求起源谷歌,那client_secret預期值相符。
  2. 驗證刷新令牌是否有效,以及請求中指定的客戶端 ID 是否與與刷新令牌關聯的客戶端 ID 匹配。
  3. 如果您無法驗證所有的上述標準,則返回一個HTTP 400錯誤的請求錯誤與{"error": "invalid_grant"}作為身體。
  4. 否則,使用刷新令牌中的用戶 ID 生成訪問令牌。這些令牌可以是任何字符串值,但它們必須唯一地代表令牌所針對的用戶和客戶端,並且不能被猜測。對於訪問令牌,還要記錄令牌的到期時間,通常是在您發出令牌後的一個小時。
  5. 在 HTTPS 響應的正文中返回以下 JSON 對象:
    {
    "token_type": "Bearer",
    "access_token": " ACCESS_TOKEN ",
    "expires_in": SECONDS_TO_EXPIRATION
    }
處理用戶信息請求

用戶信息終端是一個OAuth 2.0保護的資源,對鏈接的用戶返回的權利要求。實現和託管 userinfo 端點是可選的,以下用例除外:

從您的令牌端點成功檢索訪問令牌後,Google 會向您的 userinfo 端點發送請求,以檢索有關鏈接用戶的基本個人資料信息。

userinfo 端點請求標頭
Authorization header Bearer 類型的訪問令牌。

例如,如果你的用戶信息終端可在https://myservice.example.com/userinfo ,請求看起來像下面這樣:

GET /userinfo HTTP/1.1
Host: myservice.example.com
Authorization: Bearer ACCESS_TOKEN

要讓您的 userinfo 端點處理請求,請執行以下步驟:

  1. 從 Authorization 標頭中提取訪問令牌並返回與訪問令牌關聯的用戶的信息。
  2. 如果訪問令牌無效,返回HTTP 401錯誤未經授權使用的WWW-Authenticate響應頭。下面是一個userinfo的錯誤響應的一個示例:
    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: error="invalid_token",
    error_description="The Access Token expired"
    
    如果一個401未經授權,或任何其它不成功錯誤響應在關聯過程返回時,誤差將是不可恢復的,所檢索的令牌將被丟棄,並且用戶將必須再次啟動鏈接過程。
  3. 如果訪問令牌是有效的,回國與以下JSON對象在HTTPS響應的身體HTTP 200回應:

    {
    "sub": "USER_UUID",
    "email": "EMAIL_ADDRESS",
    "given_name": "FIRST_NAME",
    "family_name": "LAST_NAME",
    "name": "FULL_NAME",
    "picture": "PROFILE_PICTURE",
    }
    
    如果你的用戶信息端點返回一個HTTP 200成功響應,檢索到的令牌和索賠登記針對用戶的谷歌帳戶。

    用戶信息端點響應
    sub標識系統中用戶的唯一 ID。
    email用戶的電子郵件地址。
    given_name可選:用戶的名字。
    family_name可選:用戶的姓氏。
    name可選:用戶的全名。
    picture可選:用戶的檔案圖片。

驗證實作

您可以通過使用驗證實現的OAuth 2.0遊樂場工具。

在工具中,執行以下步驟:

  1. 單擊配置打開的OAuth 2.0配置窗口。
  2. OAuth流場中,選擇客戶端
  3. OAuth端點字段中,選擇自定義
  4. 在相應字段中指定您的 OAuth 2.0 端點和您分配給 Google 的客戶端 ID。
  5. 步驟1部分,不要選擇任何谷歌範圍。相反,將此字段留空或鍵入對您的服務器有效的範圍(如果不使用 OAuth 範圍,則輸入任意字符串)。當您完成後,單擊授權的API。
  6. 步驟2步驟3段,完成OAuth 2.0流程和驗證每個步驟按預期工作。

您可以通過驗證您的實現谷歌帳戶鏈接演示工具。

在工具中,執行以下步驟:

  1. 點擊登錄在與谷歌按鈕。
  2. 選擇您要關聯的帳戶。
  3. 輸入服務標識。
  4. (可選)輸入您將請求訪問的一個或多個範圍。
  5. 單擊開始演示
  6. 出現提示時,確認您可以同意並拒絕鏈接請求。
  7. 確認您被重定向到您的平台。