使用 Google 的 OpenIDConnect 身份验证系统时,可以在
email
参数中指定 profile
或 scope
或两者都指定。如果您请求 email
范围,“email”和“email_verified”声明将包含在 id_token
中,作为成功的 OAuth2 身份验证会话的一部分返回。
这是来自 Google 文档的示例 :
ID 令牌的有效负载
ID 令牌是包含一组名称/值对的 JSON 对象。 这是一个示例,为了便于阅读而进行了格式化:
{"iss":"accounts.google.com",
"at_hash":"HK6E_P6Dh8Y93mRNtsDB1Q",
"email_verified":"true",
"sub":"10769150350006150715113082367",
"azp":"1234987819200.apps.googleusercontent.com",
"email":"[email protected]",
"aud":"1234987819200.apps.googleusercontent.com",
"iat":1353601026,
"exp":1353604926,
"hd":"example.com"
}
但是,请求
profile
范围似乎对 id_token 的内容没有任何影响。为了检索配置文件信息,您必须向不同的端点发出单独的 HTTP 请求(使用您刚刚收到的 access_token 进行身份验证)以获得看起来非常相似但包含更多信息的文档:
{
"kind": "plus#personOpenIdConnect",
"gender": string,
"sub": string,
"name": string,
"given_name": string,
"family_name": string,
"profile": string,
"picture": string,
"email": string,
"email_verified": "true",
"locale": string,
"hd": string
}
理想情况下,我更愿意获取包含在 id_token JWT 中的个人资料信息(实际上只是
name
),而不是必须进行单独的调用。有没有办法指定其他字段并将它们作为声明包含在 id_token 中?如果不是,为什么要对email
进行特殊处理并在id_token中返回?
从今天开始,您将在令牌端点交换代码时获得个人资料信息(即使用“代码流”)。
如何使用: 将
profile
范围添加到您的请求中,并确保您使用的是 OpenID Connect 兼容端点(https://accounts.google.com/.well-known/openid 中列出的端点) -配置)。
在这些 ID 令牌响应中查找诸如
name
和 picture
之类的声明。与之前一样,如果 email
范围在您的请求中,则 ID 令牌将包含电子邮件相关的声明。
当您刷新访问令牌时,与新访问令牌一起返回的 ID 令牌通常也会包含这些附加声明。您可以检查这些字段,如果存在(并且与您存储的不同),请更新您的用户的个人资料。这对于检测姓名或电子邮件地址更改很有用。
当使用
response_type=id_token
和配置文件在类似 scope=openid+profile+email
的范围内发出请求时,生成的 id 令牌应直接包含配置文件声明。
这是根据 OpenID Connect 规范第 5.4 节,其中规定“...当没有颁发访问令牌时(response_type
值
id_token
就是这种情况),生成的声明将在 ID 中返回令牌。”但是,在我对他们的
OAuth 2 Playground 进行的一些测试中,即使 response_type=id_token
并且没有颁发访问令牌,Google 似乎也没有将个人资料声明放入 id 令牌中。我认为这是谷歌方面的一个实现缺陷,如果他们不解决这个问题(或添加对“claims”请求参数的支持),似乎没有办法完成你的任务正在寻找。
const { code } = req.body;
const clientId = process.env.GOOGLE_CLIENT_ID;
const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
const redirectUri = process.env.CLIENT_URL + '/googleLogin'; // You can add your own url here
const tokenEndpoint = 'https://oauth2.googleapis.com/token';
// Exchange authorization code for access token and ID token
const response = await axios.post(
tokenEndpoint,
qs.stringify({
code: code,
client_id: clientId,
client_secret: clientSecret,
redirect_uri: redirectUri,
grant_type: 'authorization_code',
}),
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
);
const idToken = response.data.id_token;
const decoded = jwt.decode(idToken);
const email = decoded?.email;
以下是所涉及关键步骤的细分:
获取授权码: 在用户完成 Google 登录流程后,我们首先从用户的浏览器获取授权码。
用代码交换代币: 我们向 Google OAuth 2.0 令牌端点发出 POST 请求,提供授权代码以及我们的客户端 ID、客户端密钥和重定向 URI。 Google 使用访问令牌(用于 API 调用)和 ID 令牌(包含用户信息)进行响应。
从ID Token中提取用户信息: 我们使用 JWT 库解码 ID 令牌,揭示用户的电子邮件地址和其他相关详细信息。
无需额外的 API 调用: 至关重要的是,我们不需要对 Google 进行任何进一步的 API 调用来检索用户信息 - 它全部包含在 ID 令牌中!