總覽
OAuth 式 Google 登入簡化連結會在 OAuth 連結之外新增 Google 登入。這不僅能為 Google 使用者提供流暢的連結體驗,還能啟用帳戶,讓使用者透過自己的 Google 帳戶建立新帳戶。
如要透過 OAuth 和 Google 登入功能連結帳戶,請按照下列一般步驟操作:
- 首先,請要求使用者同意存取自己的 Google 個人資料。
- 使用設定檔中的資訊,確認使用者帳戶是否存在。
- 如果是現有使用者,請連結帳戶。
- 如果您在驗證系統中找不到相符的 Google 使用者,請驗證 Google 收到的 ID 權杖。接著,您可以根據 ID 權杖中包含的設定檔資訊建立使用者。
![這張圖表顯示了使用者透過簡化連結流程連結 Google 帳戶的步驟。第一張螢幕截圖顯示使用者如何選取應用程式進行連結。第二張螢幕截圖可讓使用者確認服務上是否已有帳戶。第三個螢幕截圖可讓使用者選取要連結的 Google 帳戶。第四張螢幕截圖顯示 Google 應用程式與應用程式之間的連結。第五張螢幕截圖顯示 Google 應用程式中已成功連結的使用者帳戶。](https://developers.google.cn/static/identity/account-linking/images/streamlined-linking-flow.png?authuser=3&hl=zh-tw)
圖 1. 使用者可透過簡化連結的方式在手機上連結自己的帳戶
簡化連結的相關規定
- 實作基本網站 OAuth 連結流程。您的服務必須支援符合 OAuth 2.0 規定的授權和憑證交換端點。
- 您的權杖交換端點必須支援 JSON Web Token (JWT) 宣告,並導入
check
、create
和get
意圖。
實作 OAuth 伺服器
您的權杖交換端點必須支援 check
、create
、get
意圖。下圖顯示透過帳戶連結流程完成的步驟,並指出呼叫不同意圖的時機:
- 使用者在驗證系統中是否有帳戶?(使用者選取「是」或「否」即可決定)
- 是:使用者是否透過與 Google 帳戶相關聯的電子郵件地址登入平台?(使用者選取「是」或「否」即可決定)
- 是:使用者在驗證系統中是否有相符的帳戶?(系統會呼叫
check intent
進行確認)- 是:系統會呼叫
get intent
,如果成功擷取意圖,系統就會連結帳戶。 - 否:建立新帳戶?(使用者選取「是」或「否」即可決定)
- 是:系統會呼叫
create intent
,並在建立意圖傳回成功時連結帳戶。 - 否:系統會觸發網路 OAuth 流程、將使用者導向瀏覽器,且使用者可選擇連結其他電子郵件地址。
- 是:系統會呼叫
- 是:系統會呼叫
- 否:系統會觸發網路 OAuth 流程,系統會將使用者導向使用者瀏覽器,並讓使用者選擇連結其他電子郵件。
- 是:使用者在驗證系統中是否有相符的帳戶?(系統會呼叫
- 否:使用者在驗證系統中是否有相符的帳戶?(系統會呼叫
check intent
進行確認)- 是:系統會呼叫
get intent
,如果成功擷取意圖,系統就會連結帳戶。 - 否:系統會呼叫
create intent
,並在建立意圖傳回成功時連結帳戶。
- 是:系統會呼叫
- 是:使用者是否透過與 Google 帳戶相關聯的電子郵件地址登入平台?(使用者選取「是」或「否」即可決定)
检查现有用户帐号(检查 intent)
在用户同意访问其 Google 个人资料后,Google 会发送一个请求,其中包含 Google 用户身份的签名断言。该断言包含用户的 Google 帐号 ID、姓名和电子邮件地址。为您的项目配置的令牌交换端点会处理该请求。
如果您的身份验证系统中已存在相应的 Google 帐号,则您的令牌交换端点会返回 account_found=true
。如果 Google 帐号与现有用户不匹配,那么您的令牌交换端点会返回 account_found=false
的 HTTP 404 Not Found 错误。
请求的格式如下:
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&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET
您的令牌交换端点必须能够处理以下参数:
令牌端点参数 | |
---|---|
intent |
对于这些请求,此参数的值为 check 。 |
grant_type |
要交换的令牌的类型。对于这些请求,此参数的值为 urn:ietf:params:oauth:grant-type:jwt-bearer 。 |
assertion |
一个 JSON Web 令牌 (JWT),用于提供 Google 用户身份的签名断言。JWT 包含用户的 Google 帐号 ID、姓名和电子邮件地址等信息。 |
client_id |
您分配给 Google 的客户端 ID。 |
client_secret |
您分配给 Google 的客户端密钥。 |
为了响应 check
intent 请求,您的令牌交换端点必须执行以下步骤:
- 验证并解码 JWT 断言。
- 检查您的身份验证系统中是否已存在该 Google 帐号。
驗證並解碼 JWT 斷言
您可以使用 適用於您語言的 JWT 解碼程式庫。使用 Google 的公開金鑰,位於 JWK 或 使用 PEM 格式進行驗證 憑證的簽章
解碼後的 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
欄位)。
您可以使用 email
、email_verified
和 hd
欄位判斷
Google 代管且具公信力的電子郵件地址。如果 Google
權威使用者目前是合法帳戶擁有者
可以略過密碼或其他驗證方式此外,這些方法
可用於驗證帳戶再建立連結。
Google 具有公信力的案例:
email
的尾碼是@gmail.com
,這是 Gmail 帳戶。- 「
email_verified
」為 true,且已設定「hd
」,代表這是 G Suite 帳戶。
使用者註冊 Google 帳戶時,不必使用 Gmail 或 G Suite。時間
email
未包含 @gmail.com
後置字串,且 hd
不是 Google
建議使用權威性密碼、密碼或其他驗證方法
使用者。email_verified
也可能是 true,因為 Google 一開始就驗證過
使用者就是 Google 帳戶建立時的使用者,但第三方的擁有權
電子郵件帳戶可能會有所變更。
检查您的身份验证系统中是否已存在该 Google 帐号
检查是否满足以下任一条件:
- Google 帐号 ID 可在用户的数据库中找到,可在断言的
sub
字段找到。 - 断言中的电子邮件地址与您的用户数据库中的用户匹配。
如果其中任一条件为 true,则表示用户已注册。在这种情况下,系统将返回如下所示的响应:
HTTP/1.1 200 Success Content-Type: application/json;charset=UTF-8 { "account_found":"true", }
如果断言中指定的 Google 帐号 ID 和电子邮件地址都与用户数据库中的用户不匹配,则表示用户尚未注册。在这种情况下,您的令牌交换端点需要使用包含 "account_found": "false"
的 HTTP 404 错误进行响应,如以下示例所示:
HTTP/1.1 404 Not found Content-Type: application/json;charset=UTF-8 { "account_found":"false", }
处理自动链接(获取 intent)
在用户同意访问其 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&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET
您的令牌交换端点必须能够处理以下参数:
令牌端点参数 | |
---|---|
intent |
对于这些请求,此参数的值为 get 。 |
grant_type |
要交换的令牌的类型。对于这些请求,此参数的值为 urn:ietf:params:oauth:grant-type:jwt-bearer 。 |
assertion |
一个 JSON Web 令牌 (JWT),用于提供 Google 用户身份的签名断言。JWT 包含用户的 Google 帐号 ID、姓名和电子邮件地址等信息。 |
scope |
可选:您已将 Google 配置为向用户请求的任何范围。 |
client_id |
您分配给 Google 的客户端 ID。 |
client_secret |
您分配给 Google 的客户端密钥。 |
为了响应 get
intent 请求,您的令牌交换端点必须执行以下步骤:
- 验证并解码 JWT 断言。
- 检查您的身份验证系统中是否已存在该 Google 帐号。
驗證並解碼 JWT 斷言
您可以使用 適用於您語言的 JWT 解碼程式庫。使用 Google 的公開金鑰,位於 JWK 或 使用 PEM 格式進行驗證 憑證的簽章
解碼後的 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
欄位)。
您可以使用 email
、email_verified
和 hd
欄位判斷
Google 代管且具公信力的電子郵件地址。如果 Google
權威使用者目前是合法帳戶擁有者
可以略過密碼或其他驗證方式此外,這些方法
可用於驗證帳戶再建立連結。
Google 具有公信力的案例:
email
的尾碼是@gmail.com
,這是 Gmail 帳戶。- 「
email_verified
」為 true,且已設定「hd
」,代表這是 G Suite 帳戶。
使用者註冊 Google 帳戶時,不必使用 Gmail 或 G Suite。時間
email
未包含 @gmail.com
後置字串,且 hd
不是 Google
建議使用權威性密碼、密碼或其他驗證方法
使用者。email_verified
也可能是 true,因為 Google 一開始就驗證過
使用者就是 Google 帳戶建立時的使用者,但第三方的擁有權
電子郵件帳戶可能會有所變更。
检查您的身份验证系统中是否已存在该 Google 帐号
检查是否满足以下任一条件:
- Google 帐号 ID 可在用户的数据库中找到,可在断言的
sub
字段找到。 - 断言中的电子邮件地址与您的用户数据库中的用户匹配。
如果找到了用户的帐号,请发出访问令牌,并在 HTTPS 响应的正文中以 JSON 对象形式返回值,如以下示例所示:
{ "token_type": "Bearer", "access_token": "ACCESS_TOKEN", "expires_in": SECONDS_TO_EXPIRATION }
在某些情况下,基于 ID 令牌的帐号关联可能会为用户失败。如果出现任何此类情况,您的令牌交换端点都需要使用返回 error=linking_error
的 HTTP 401 错误进行响应,如以下示例所示:
HTTP/1.1 401 Unauthorized Content-Type: application/json;charset=UTF-8 { "error":"linking_error", "login_hint":"foo@bar.com" }
Google 收到包含 linking_error
的 401 错误响应后,会将用户作为授权参数 login_hint
发送到您的授权端点。用户在浏览器中使用 OAuth 关联流程完成帐号关联。
透過 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&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET
您的權杖交換端點必須能夠處理下列參數:
權杖端點參數 | |
---|---|
intent |
針對這些請求,這個參數的值為 create 。 |
grant_type |
交換的權杖類型。針對這些要求,這個參數的值為 urn:ietf:params:oauth:grant-type:jwt-bearer 。 |
assertion |
JSON Web Token (JWT) 提供已簽署的 Google 使用者身分宣告。JWT 內含使用者 Google 帳戶 ID、名稱和電子郵件地址等資訊。 |
client_id |
您指派給 Google 的用戶端 ID。 |
client_secret |
您指派給 Google 的用戶端密鑰。 |
assertion
參數中的 JWT 包含使用者的 Google 帳戶 ID、名稱和電子郵件地址,可用來在您的服務中建立新帳戶。
如要回應 create
意圖要求,您的權杖交換端點必須執行下列步驟:
- 驗證並解碼 JWT 宣告。
- 驗證使用者資訊及建立新帳戶。
驗證並解碼 JWT 斷言
您可以使用 適用於您語言的 JWT 解碼程式庫。使用 Google 的公開金鑰,位於 JWK 或 使用 PEM 格式進行驗證 憑證的簽章
解碼後的 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
欄位)。
您可以使用 email
、email_verified
和 hd
欄位判斷
Google 代管且具公信力的電子郵件地址。如果 Google
權威使用者目前是合法帳戶擁有者
可以略過密碼或其他驗證方式此外,這些方法
可用於驗證帳戶再建立連結。
Google 具有公信力的案例:
email
的尾碼是@gmail.com
,這是 Gmail 帳戶。- 「
email_verified
」為 true,且已設定「hd
」,代表這是 G Suite 帳戶。
使用者註冊 Google 帳戶時,不必使用 Gmail 或 G Suite。時間
email
未包含 @gmail.com
後置字串,且 hd
不是 Google
建議使用權威性密碼、密碼或其他驗證方法
使用者。email_verified
也可能是 true,因為 Google 一開始就驗證過
使用者就是 Google 帳戶建立時的使用者,但第三方的擁有權
電子郵件帳戶可能會有所變更。
驗證使用者資訊及建立新帳戶
請確認下列任一種情況是否成立:
- 這個 Google 帳戶 ID (位於宣告的
sub
欄位中) 位於使用者資料庫中。 - 宣告中的電子郵件地址與您的使用者資料庫中的使用者相符。
如果符合其中一個條件,提示使用者將現有的帳戶與 Google 帳戶連結。如要這麼做,請以指定 error=linking_error
的 HTTP 401 錯誤回應要求,並將使用者的電子郵件地址設為 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 }
取得 Google API 用戶端 ID
在帳戶連結註冊程序過程中,您必須提供 Google API 用戶端 ID。
如要取得在完成 OAuth 連結步驟中建立的專案,取得 API 用戶端 ID。如要這樣做,請完成下列步驟:
- 開啟 Google API 控制台的「憑證」頁面。
建立或選取 Google API 專案。
如果專案沒有網頁應用程式類型的用戶端 ID,請按一下 [建立憑證 > OAuth 用戶端 ID] 來建立。請務必在「Authorized JavaScript origins」(已授權的 JavaScript 來源) 方塊中加入您的網站網域。執行本機測試或開發作業時,必須將「
http://localhost
」和「http://localhost:<port_number>
」新增至「Authorized JavaScript origins」(已獲授權的 JavaScript 來源) 欄位。
驗證實作
您可以通過使用驗證實現的OAuth 2.0遊樂場工具。
在工具中,執行以下步驟:
- 單擊配置 打開的OAuth 2.0配置窗口。
- 在OAuth流場中,選擇客戶端。
- 在OAuth端點字段中,選擇自定義。
- 在相應字段中指定您的 OAuth 2.0 端點和您分配給 Google 的客戶端 ID。
- 在步驟1部分,不要選擇任何谷歌範圍。相反,將此字段留空或鍵入對您的服務器有效的範圍(如果不使用 OAuth 範圍,則輸入任意字符串)。當您完成後,單擊授權的API。
- 在步驟2和步驟3段,完成OAuth 2.0流程和驗證每個步驟按預期工作。
您可以通過驗證您的實現谷歌帳戶鏈接演示工具。
在工具中,執行以下步驟:
- 點擊登錄在與谷歌按鈕。
- 選擇您要關聯的帳戶。
- 輸入服務標識。
- (可選)輸入您將請求訪問的一個或多個範圍。
- 單擊開始演示。
- 出現提示時,確認您可以同意並拒絕鏈接請求。
- 確認您被重定向到您的平台。