是否可以从 Google 获取 id_token 中的个人资料信息?

问题描述 投票:0回答:4

使用 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中返回?

oauth-2.0 google-openid openid-connect google-oauth
4个回答
17
投票

从今天开始,您将在令牌端点交换代码时获得个人资料信息(即使用“代码流”)。

如何使用:

profile
范围添加到您的请求中,并确保您使用的是 OpenID Connect 兼容端点(https://accounts.google.com/.well-known/openid 中列出的端点) -配置)。

在这些 ID 令牌响应中查找诸如

name
picture
之类的声明。与之前一样,如果
email
范围在您的请求中,则 ID 令牌将包含电子邮件相关的声明。

当您刷新访问令牌时,与新访问令牌一起返回的 ID 令牌通常也会包含这些附加声明。您可以检查这些字段,如果存在(并且与您存储的不同),请更新您的用户的个人资料。这对于检测姓名或电子邮件地址更改很有用。


7
投票

当使用

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”请求参数的支持),似乎没有办法完成你的任务正在寻找。


1
投票
嗯,这是提出请求的正确地点。我们正在努力支持此功能,并且应该很快(在接下来的几周内)推出。然后我会更新此回复。


0
投票
是的,有可能,我很高兴分享我已经成功实现了 Google 登录功能!

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;
以下是所涉及关键步骤的细分:

  1. 获取授权码: 在用户完成 Google 登录流程后,我们首先从用户的浏览器获取授权码。

  2. 用代码交换代币: 我们向 Google OAuth 2.0 令牌端点发出 POST 请求,提供授权代码以及我们的客户端 ID、客户端密钥和重定向 URI。 Google 使用访问令牌(用于 API 调用)和 ID 令牌(包含用户信息)进行响应。

  3. 从ID Token中提取用户信息: 我们使用 JWT 库解码 ID 令牌,揭示用户的电子邮件地址和其他相关详细信息。

  4. 无需额外的 API 调用: 至关重要的是,我们不需要对 Google 进行任何进一步的 API 调用来检索用户信息 - 它全部包含在 ID 令牌中!

这花费了我很多时间,我希望这可能会有所帮助。谷歌文档在这方面非常糟糕。

© www.soinside.com 2019 - 2024. All rights reserved.