您可以允许用户在输入功能受限的设备(例如连接到互联网的电视)上使用其 Google 帐号登录您的应用。
应用会向用户显示简短代码和登录网址。然后,用户在网络浏览器中打开登录网址,输入代码,并授予应用访问用户登录信息的权限。最后,应用收到确认消息,用户随即登录
如需使用此登录流程,应用必须在满足以下条件的设备上运行:
- 设备必须能够显示 40 个字符的网址和 15 个字符的用户代码,以及向用户的说明。
- 设备必须连接到互联网。
获取客户端 ID 和客户端密钥
您的应用需要 OAuth 2.0 客户端 ID 和客户端密钥才能向 Google 的登录端点发出请求。
如需查找项目的客户端 ID 和客户端密钥,请执行以下操作:
- 选择现有的 OAuth 2.0 凭据或打开“凭据”页面。
- 如果您尚未创建项目的 OAuth 2.0 凭据,请依次点击创建凭据 > OAuth 客户端 ID,并提供创建凭据所需的信息。
- 在 OAuth 2.0 客户端 ID 部分查找客户端 ID。如需了解详情,请点击客户端 ID。
如要创建新的客户端 ID,请选择电视和受限输入设备应用类型。
获取用户代码和验证网址
用户请求使用 Google 帐号登录后,您可以通过向 OAuth 2.0 设备端点 https://oauth2.googleapis.com/device/code
发送 HTTP POST 请求来获取用户代码和验证网址。在请求中附上您的客户端 ID 和所需范围列表。如果您只想让用户使用他们的 Google 帐号登录,请仅请求 profile
和 email
范围;或者,如果您想请求代表用户调用支持的 API 的权限,则除了 profile
和 email
范围之外,还可以请求所需的范围。
以下是一个用户代码请求示例:
POST /device/code HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
client_id=YOUR_GOOGLE_CLIENT_ID&scope=email%20profile
使用 curl
:
curl -d "client_id=YOUR_GOOGLE_CLIENT_ID&scope=email profile" https://oauth2.googleapis.com/device/code
响应以 JSON 对象的形式返回:
{
"device_code" : "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8",
"user_code" : "GQVQ-JKEC",
"verification_url" : "https://www.google.com/device",
"expires_in" : 1800,
"interval" : 5
}
您的应用向用户显示 user_code
和 verification_url
值,并同时轮询指定 interval
处的登录端点,直到用户登录或 expires_in
指定的时间为止。
显示用户代码和验证网址
从设备端点收到用户代码和验证网址后,显示这些内容,并指示用户打开网址并输入用户代码。
verification_url
和 user_code
的值可能会发生变化。请以能够处理以下限制的方式设计界面:
user_code
必须显示在足够宽的字段中,以处理 15 个W
大小的字符。verification_url
必须显示在足够宽的字段中,以处理长度为 40 个字符的网址字符串。
这两个字符串均可包含 US-ASCII 字符集中的任何可打印字符。
显示 user_code
字符串时,请勿以任何方式修改该字符串(例如,更改大小写或插入其他格式字符),因为如果以后代码格式发生更改,应用可能会中断。
如果您愿意,可以修改 verification_url
字符串,只需从网址中去除架构以便显示即可。如果您这样做,请确保您的应用可以同时处理“http”和“https”变体。请勿以其他方式修改 verification_url
字符串。
当用户导航到验证网址时,会看到如下所示的页面:
用户输入用户代码后,Google 登录网站会显示一个类似于以下内容的同意屏幕:
如果用户点击允许,您的应用可以获得一个 ID 令牌(用于识别用户)、一个访问令牌(用于调用 Google API)以及一个刷新令牌(用于获取新令牌)。
获取 ID 令牌和刷新令牌
应用显示用户代码和验证网址后,开始使用您从设备端点接收的设备代码轮询令牌端点 (https://oauth2.googleapis.com/token
)。按照 interval
值指定的时间间隔(以秒为单位)轮询令牌端点。
以下是一个示例请求:
POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded
client_id=YOUR_GOOGLE_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&code=DEVICE_CODE&grant_type=http://oauth.net/grant_type/device/1.0
使用 curl
:
curl -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&code=YOUR_DEVICE_CODE&grant_type=http://oauth.net/grant_type/device/1.0" https://oauth2.googleapis.com/token
如果用户尚未批准请求,则响应如下所示:
{
"error" : "authorization_pending"
}
您的应用应以不超过 interval
的值的频率重复这些请求。如果您的应用轮询速度过快,则响应将如下所示:
{
"error" : "slow_down"
}
用户登录并向您的应用授予对您请求的范围的访问权限后,对应用下一个请求的响应中会包含 ID 令牌、访问令牌和刷新令牌:
{
"access_token": "ya29.AHES6ZSuY8f6WFLswSv0HZLP2J4cCvFSj-8GiZM0Pr6cgXU",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "1/551G1yXUqgkDGnkfFk6ZbjMMMDIMxo3JFc8lY8CAR-Q",
"id_token": "eyJhbGciOiJSUzI..."
}
收到此响应后,您的应用可以解码 ID 令牌以获取已登录用户的基本个人资料信息,或将 ID 令牌发送到应用的后端服务器,以便安全地向服务器进行身份验证。此外,您的应用还可以使用访问令牌来调用用户授权的 Google API。
ID 和访问令牌的生命周期有限。若要在令牌的生命周期结束后让用户保持登录状态,请存储刷新令牌并使用它来请求新令牌。
从 ID 令牌中获取用户个人资料信息
您可以使用任何 JWT 解码库对 ID 令牌进行解码,获取已登录用户的个人资料信息。例如,使用 Auth0 jwt-decode JavaScript 库:
var user_profile = jwt_decode(<var>id_token</var>);
// The "sub" field is available on all ID tokens. This value is unique for each
// Google account and can be used to identify the user. (But do not send this
// value to your server; instead, send the whole ID token so its authenticity
// can be verified.)
var user_id = user_profile["sub"];
// These values are available when you request the "profile" and "email" scopes.
var user_email = user_profile["email"];
var email_verified = user_profile["email_verified"];
var user_name = user_profile["name"];
var user_photo_url = user_profile["picture"];
var user_given_name = user_profile["given_name"];
var user_family_name = user_profile["family_name"];
var user_locale = user_profile["locale"];
更多信息
- 如果希望用户在 ID 令牌的生命周期过后继续保持登录状态,请参阅刷新访问令牌。
- 如果您需要使用后端服务器进行身份验证,请参阅使用后端服务器进行身份验证,了解如何安全地执行此操作。