关于id_token vs access_token的澄清

时间:2017-10-11 07:07:19

标签: oauth-2.0 access-token openid-connect oidc

我正在使用OIDC和OAuth 2.0构建系统(使用Auth0),并且我不确定如何正确使用id_tokenaccess_token。或者更确切地说,我对在我的设置中分配给各种服务的角色感到困惑。

我有一个完全静态的前端应用程序(单页面应用程序,HTML + JS,没有后端),可确保使用针对Auth0的隐式流程对用户进行身份验证。然后,前端应用程序从我正在构建的API中获取数据。

现在,哪个是对的?

  • 前端SPA是OAuth 客户端应用程序
  • 我的API服务是OAuth 资源服务器

...或:

  • 前端和我的API服务都是客户端应用程序

如果我的前端和后端API都可以被认为是客户端,我认为使用id_token作为承载令牌对我的前端到后端的请求没有任何实际损害 - 这很有吸引力因为那时我可以简单地验证后端的签名令牌,并且我拥有所需的所有用户信息。但是,如果我的API被视为资源服务器,我应该使用access_token,但是我必须在每个API请求上连接到Auth0的服务器以验证令牌,并获得基本的用户信息,赢了吗?

我已阅读this,这似乎表明access_token是唯一可用于我的API的有效令牌。但就像我说的那样,我不确定个别服务的角色。使用id_token很有诱惑力,因为它不需要后端的网络连接,并且包含提取正确数据所需的信息。

正确的方法是什么?

4 个答案:

答案 0 :(得分:2)

您的前端是您的OAuth客户端应用程序,一旦它存储令牌并可以对OAuth流采取操作。您的API服务是资源服务,因为它接受您的身份服务器发出的access_token。

另外我会说你的id_token代表已登录用户的身份,可能包含你应用的敏感数据。 access_token是您访问资源的凭据。

最后,您将使用access_token来请求资源,而如果您需要来自登录用户(资源所有者)的特定数据,您可以从令牌端点请求ID令牌。

答案 1 :(得分:1)

在我看来,第一种方法是正确的。您的SPA是客户端应用程序,您的API是资源服务器。

我建议你限制id_token的使用,直到你的SPA为止。您可以使用ID令牌中的基本信息(如用户名和电子邮件)在UI中显示用户信息。如果您也可以将访问令牌生成为JWT,那么您的API可以验证访问令牌而无需转到身份提供者。您可以在访问令牌中包含角色(或类似角色),以获取访问令牌中的授权信息。

答案 2 :(得分:0)

我喜欢这篇有关差异的中型帖子,所有内容都感谢这位作者。

https://medium.com/@nilasini/id-token-vs-access-token-17e7dd622084

如果您像我一样使用Azure AD B2C,则可以在此处阅读更多信息:

https://docs.microsoft.com/en-us/azure/active-directory-b2c/openid-connect

ID令牌

如果将作用域用作openid,则将获得id令牌。 id令牌特定于openid范围。使用openid范围,您可以同时获取id令牌和访问令牌。

OpenID Connect对OAuth 2.0进行的主要扩展(用于使最终用户能够通过身份验证)是ID令牌数据结构。 ID令牌是一种安全令牌,其中包含与使用客户端时授权服务器进行的最终用户身份验证有关的Claims(声明是包含用户信息的名称/值对),并可能包含其他请求的Claims。 ID令牌表示为JSON Web Token (JWT)

{
   "iss": "https://server.example.com",
   "sub": "24400320",
   "aud": "s6BhdRkqt3",
   "nonce": "n-0S6_WzA2Mj",
   "exp": 1311281970,
   "iat": 1311280970,
   "auth_time": 1311280969,
   "acr": "urn:mace:incommon:iap:silver"
}

以上是默认的JWT索赔,此外,如果您向服务提供商要求索赔,那么您也将获得这些索赔。

根据OIDC规范,id_token是JWT。这意味着:

    关于用户的
  • 身份信息直接编码在令牌中 和
  • 可以确定地验证令牌以证明它尚未被验证 被篡改。

规范中有一组rules用于验证id_token。在id_token中编码的声明中有一个有效期(exp),必须将其视为验证过程的一部分。此外,JWT的签名部分与密钥配合使用,以验证整个JWT未被以任何方式篡改。

访问令牌

访问令牌用作承载令牌。承载令牌意味着承载者(持有访问令牌)可以访问授权资源而无需进一步标识。因此,保护​​承载令牌很重要。如果我能以某种方式获得并“承担”您的访问令牌,那么我可以假装成您。

这些令牌通常具有较短的寿命(由其到期决定),以提高安全性。也就是说,当访问令牌过期时,用户必须再次进行身份验证才能获得新的访问令牌,从而限制了它是不记名令牌这一事实的暴露。

尽管OIDC规范没有强制要求,但Okta使用JWT作为访问令牌,因为(除其他外)过期是直接内置在令牌中的。

OIDC指定一个/ userinfo端点,该端点返回身份信息并且必须受到保护。呈现访问令牌使端点可以访问。

http://openid.net/specs/openid-connect-core-1_0.html https://connect2id.com/learn/openid-connect#cool-id-token-uses https://developer.okta.com/blog/2017/07/25/oidc-primer-part-1

答案 3 :(得分:0)

我还想知道,如果我使用从 IdP 收到的令牌,是否需要在每次请求时都与 IdP 交谈。我最终得到了以下设置:

  • 只有后端与 IdP 对话,前端不会。
  • 在 IdP 回调后,后端会为前端发出 JWT。
  • 用户会话和前端-后端通信完全由我的应用使用 JWT 令牌进行管理。

查看这篇文章:OAuth2 in NestJS for Social Login (Google, Facebook, Twitter, etc)

和这个仓库:https://github.com/thisismydesign/nestjs-starter

还有这个问题:OAuth2 flow in full-stack NestJS application