簡化了與OAuth和Google登錄的鏈接

概述

基於OAuth的Google登錄精簡鏈接OAuth鏈接之上添加了Google登錄。這為Google用戶提供了無縫的鏈接體驗,還為使用非Google身份註冊到您的服務的用戶啟用了帳戶鏈接。

要執行與OAuth和Google登錄的帳戶鏈接,請遵循以下常規步驟:

  1. 首先,請用戶同意訪問其Google個人資料。
  2. 使用他們的個人資料中的信息來檢查用戶帳戶是否存在。
  3. 對於現有用戶,請鏈接帳戶。
  4. 如果在身份驗證系統中找不到與Google用戶匹配的內容,請驗證從Google收到的ID令牌。然後,您可以基於ID令牌中包含的配置文件信息創建用戶。

圖3 。使用簡化的鏈接在用戶電話上進行帳戶鏈接

帳戶使用行業標準的OAuth 2.0隱式授權代碼流進行鏈接。您的服務必須支持符合OAuth 2.0的授權令牌交換端點。此外,令牌交換端點應支持JSON Web令牌(JWT)斷言,並實現checkcreateget intent。

獲取您的Google API客戶端ID和機密

在完成OAuth鏈接步驟時,您需要使用創建的項目來獲取API客戶端ID和密碼。為此,請完成以下步驟:

  1. 打開Google API控制台的“憑據”頁面。
  2. 創建或選擇一個Google API項目。

    如果您的項目沒有Web應用程序類型的客戶端ID,請單擊創建憑據> OAuth客戶端ID創建一個。確保在“授權JavaScript來源”框中包含您網站的域。在執行本地測試或開發時,必須將http://localhosthttp://localhost:<port_number>Authorized JavaScript origins字段。

實施您的OAuth服務器

檢查現有的用戶帳戶

用戶同意訪問其Google個人資料後,Google會發送請求,其中包含對Google用戶身份的簽名聲明。斷言包含的信息包括用戶的Google帳戶ID,名稱和電子郵件地址。為您的項目配置的令牌交換端點處理該請求。

如果您的身份驗證系統中已經存在相應的Google帳戶,則令牌交換端點將以account_found=true響應。如果Google帳戶與現有用戶不匹配,則令牌交換端點將返回一個HTTP 404 Not Found錯誤,帶有account_found=false

該請求具有以下形式:

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

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&intent=check&assertion=JWT&scope=SCOPES

您的令牌交換端點必須能夠處理以下參數:

令牌端點參數
intent對於這些請求,此參數的值為check
grant_type交換令牌的類型。對於這些請求,此參數的值為urn:ietf:params:oauth:grant-type:jwt-bearer
assertion JSON Web令牌(JWT),提供對Google用戶身份的簽名斷言。 JWT包含的信息包括用戶的Google帳戶ID,名稱和電子郵件地址。

當您的令牌交換端點接收到check請求時,它需要驗證和解碼JWT斷言。

驗證並解碼JWT斷言

您可以使用針對您的語言JWT解碼庫來驗證和解碼JWT斷言。使用Google的JWKPEM格式的公鑰來驗證令牌的簽名。

解碼後,JWT斷言類似於以下示例:

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

除了驗證令牌的簽名外,還要驗證斷言的頒發者( iss字段)為https://accounts.google.com ,受眾( aud字段)是您分配的客戶端ID,並且令牌尚未過期( exp場地)。

使用emailemail_verifiedhd字段,您可以確定Google是否託管電子郵件地址並對其具有權威性。如果Google具有權威性,則當前已知該用戶為合法帳戶所有者,您可以跳過密碼或其他挑戰方法。否則,可以使用這些方法在鏈接之前驗證帳戶。

Google具有權威性的情況:

  • email後綴為@gmail.com ,這是一個Gmail帳戶。
  • email_verified為true並且設置了hd ,這是一個G Suite帳戶。

用戶可以在不使用Gmail或G Suite的情況下註冊Google帳戶。如果email不包含@gmail.com後綴,並且hd缺失,則Google不具有權威性,建議使用密碼或其他挑戰方法來驗證用戶。當Google在創建Google帳戶時最初驗證了用戶時, email_verfied也可能為true,但是此後第三方電子郵件帳戶的所有權可能已更改。

檢查您的身份驗證系統中是否已存在Google帳戶

檢查以下條件之一是否成立:

  • 在斷言的sub字段中找到的Google帳戶ID在您的用戶數據庫中。
  • 斷言中的電子郵件地址與您的用戶數據庫中的用戶匹配。

如果任一條件為真,則用戶已經註冊。在這種情況下,返回如下響應:

HTTP/1.1 200 Success
Content-Type: application/json;charset=UTF-8

{
  "account_found":"true",
}

然後,Google向用戶顯示一個鏈接同意對話框,並請求同意所需的範圍,以便繼續進行鏈接。 Google徵得用戶同意後,Google get向您的令牌端點發送一個get請求,以繼續進行鏈接。

如果斷言中指定的Google帳戶ID或電子郵件地址均不匹配您數據庫中的用戶,則該用戶尚未註冊。在這種情況下,令牌交換端點需要使用HTTP 404錯誤進行響應,該錯誤指定為"account_found": "false" ,如以下示例所示:

HTTP/1.1 404 Not found
Content-Type: application/json;charset=UTF-8

{
  "account_found":"false",
}
當Google收到帶有"account_found": "false"錯誤的404錯誤響應時,Google會向用戶顯示一個對話框,以請求同意創建新帳戶並訪問所需的範圍。 Google徵得用戶同意後,Google會使用設置為intent參數的值調用您的令牌交換端點,以create該令牌,並包括一個ID令牌,該令牌包含請求中的用戶個人資料信息。

處理自動鏈接

用戶同意訪問其Google個人資料後,Google會發送請求,其中包含對Google用戶身份的簽名聲明。斷言包含的信息包括用戶的Google帳戶ID,名稱和電子郵件地址。為您的項目配置的令牌交換端點處理該請求。

如果您的身份驗證系統中已經存在相應的Google帳戶,則令牌交換端點將為用戶返回令牌。如果Google帳戶與現有用戶不匹配,則令牌交換端點將返回linking_error錯誤和可選的login_hint

該請求具有以下形式:

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

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&intent=get&assertion=JWT&scope=SCOPES

您的令牌交換端點必須能夠處理以下參數:

令牌端點參數
intent對於這些請求,此參數的值為get
grant_type交換令牌的類型。對於這些請求,此參數的值為urn:ietf:params:oauth:grant-type:jwt-bearer
assertion JSON Web令牌(JWT),提供對Google用戶身份的簽名斷言。 JWT包含的信息包括用戶的Google帳戶ID,名稱和電子郵件地址。
scope可選:您已配置Google來向用戶請求的所有範圍。

當您的令牌交換端點接收到鏈接請求時,它需要驗證並解碼JWT斷言。

驗證並解碼JWT斷言

您可以使用針對您的語言JWT解碼庫來驗證和解碼JWT斷言。使用Google的JWKPEM格式的公鑰來驗證令牌的簽名。

解碼後,JWT斷言類似於以下示例:

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

除了驗證令牌的簽名外,還要驗證斷言的頒發者( iss字段)為https://accounts.google.com ,受眾( aud字段)是您分配的客戶端ID,並且令牌尚未過期( exp場地)。

使用emailemail_verifiedhd字段,您可以確定Google是否託管電子郵件地址並對其具有權威性。如果Google具有權威性,則當前已知該用戶為合法帳戶所有者,您可以跳過密碼或其他挑戰方法。否則,可以使用這些方法在鏈接之前驗證帳戶。

Google具有權威性的情況:

  • email後綴為@gmail.com ,這是一個Gmail帳戶。
  • email_verified為true並且設置了hd ,這是一個G Suite帳戶。

用戶可以在不使用Gmail或G Suite的情況下註冊Google帳戶。如果email不包含@gmail.com後綴,並且hd缺失,則Google不具有權威性,建議使用密碼或其他挑戰方法來驗證用戶。當Google在創建Google帳戶時最初驗證了用戶時, email_verfied也可能為true,但是此後第三方電子郵件帳戶的所有權可能已更改。

檢查您的身份驗證系統中是否已存在Google帳戶

檢查以下條件之一是否成立:

  • 在斷言的sub字段中找到的Google帳戶ID在您的用戶數據庫中。
  • 斷言中的電子郵件地址與您的用戶數據庫中的用戶匹配。

在某些情況下,對於用戶而言,基於ID令牌的帳戶鏈接可能會失敗。如果出於某種原因這樣做,則令牌交換端點需要使用HTTP 401錯誤進行響應,該錯誤指定error=linking_error ,如以下示例所示:

HTTP/1.1 401 Unauthorized
Content-Type: application/json;charset=UTF-8

{
  "error":"linking_error",
  "login_hint":"foo@bar.com"
}
當Google收到帶有linking_error的401錯誤響應時,Google會在請求中使用以下內容調用您的令牌交換端點:

  • 設置要createintent參數
  • 具有ID令牌和用戶個人資料信息的JWT

通過Google登錄處理帳戶創建

當用戶需要在您的服務上創建帳戶時,Google會向您的令牌交換端點發出一個請求,該端點指定intent=create

該請求具有以下形式:

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

response_type=token&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&scope=SCOPES&intent=create&assertion=JWT[&NEW_ACCOUNT_INFO]

您的令牌交換端點必須能夠處理以下參數:

令牌端點參數
intent對於這些請求,此參數的值為create
grant_type交換令牌的類型。對於這些請求,此參數的值為urn:ietf:params:oauth:grant-type:jwt-bearer
assertion JSON Web令牌(JWT),提供對Google用戶身份的簽名斷言。 JWT包含的信息包括用戶的Google帳戶ID,名稱和電子郵件地址。

assertion參數中的JWT包含用戶的Google帳戶ID,名稱和電子郵件地址,您可以使用它們在服務上創建新帳戶。

要響應帳戶創建請求,令牌交換端點必須執行以下兩個部分中的步驟。

驗證並解碼JWT斷言

您可以使用針對您的語言JWT解碼庫來驗證和解碼JWT斷言。使用Google的JWKPEM格式的公鑰來驗證令牌的簽名。

解碼後,JWT斷言類似於以下示例:

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

除了驗證令牌的簽名外,還要驗證斷言的頒發者( iss字段)為https://accounts.google.com ,受眾( aud字段)是您分配的客戶端ID,並且令牌尚未過期( exp場地)。

使用emailemail_verifiedhd字段,您可以確定Google是否託管電子郵件地址並對其具有權威性。如果Google具有權威性,則當前已知該用戶為合法帳戶所有者,您可以跳過密碼或其他挑戰方法。否則,可以使用這些方法在鏈接之前驗證帳戶。

Google具有權威性的情況:

  • email後綴為@gmail.com ,這是一個Gmail帳戶。
  • email_verified為true並且設置了hd ,這是一個G Suite帳戶。

用戶可以在不使用Gmail或G Suite的情況下註冊Google帳戶。如果email不包含@gmail.com後綴,並且hd缺失,則Google不具有權威性,建議使用密碼或其他挑戰方法來驗證用戶。當Google在創建Google帳戶時最初驗證了用戶時, email_verfied也可能為true,但是此後第三方電子郵件帳戶的所有權可能已更改。

驗證用戶信息並創建新帳戶

檢查以下條件之一是否成立:

  • 在斷言的sub字段中找到的Google帳戶ID在您的用戶數據庫中。
  • 斷言中的電子郵件地址與您的用戶數據庫中的用戶匹配。

如果任一條件成立,則提示用戶將其現有帳戶與他們的Google帳戶相關聯。為此,請使用HTTP 401錯誤響應請求,該錯誤指定error=linking_error並將用戶的電子郵件地址指定為login_hint 。以下是示例響應:

HTTP/1.1 401 Unauthorized
Content-Type: application/json;charset=UTF-8

{
  "error":"linking_error",
  "login_hint":"foo@bar.com"
}

當Google收到帶有linking_error的401錯誤響應時,Google會將用戶以login_hint作為參數發送到您的授權端點。用戶使用其瀏覽器中的OAuth鏈接流完成帳戶鏈接。

如果兩個條件都不成立,則使用JWT中提供的信息創建一個新的用戶帳戶。新帳戶通常沒有設置密碼。建議您將Google登錄功能添加到其他平台,以使用戶可以在應用程序的各個表面上使用Google登錄。或者,您可以通過電子郵件向用戶發送一個鏈接,該鏈接將啟動您的密碼恢復流程,以允許用戶設置密碼以在其他平台上登錄。

創建完成後,發出訪問令牌,然後在HTTPS響應正文中的JSON對像中返回值,如以下示例所示:

{
  "token_type": "Bearer",
  "access_token": "ACCESS_TOKEN",

  "expires_in": SECONDS_TO_EXPIRATION
}

驗證您的實施

您可以使用OAuth 2.0 Playground工具來驗證您的實施。

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

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

您可以使用Google帳戶鏈接演示工具來驗證您的實施。

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

  1. 點擊“使用Google登錄”按鈕。
  2. 選擇您要鏈接的帳戶。
  3. 輸入服務ID。
  4. (可選)輸入一個或多個您將請求訪問的作用域。
  5. 單擊開始演示
  6. 出現提示時,請確認您同意並拒絕鏈接請求。
  7. 確認您已重定向到平台。