OpenID Connect中ID令牌到期时间的意图是什么?

时间:2014-09-05 12:57:16

标签: oauth-2.0 openid-connect

在OpenID Connect中,访问令牌具有到期时间。对于授权代码流,这通常很短(例如20分钟),之后您使用刷新令牌来请求新的访问令牌。

ID令牌也有到期时间。我的问题是这是什么意思?

任何ID令牌到期时间小于刷新令牌的到期时间将意味着您最终将拥有一个过期的ID令牌,但是有效的访问令牌。

你的意思是:

  • 让您的ID令牌的到期时间超过刷新令牌的到期时间,或者
  • 将其设置为与访问令牌相同的到期时间并在其到期时采取一些操作(什么?),或
  • 只是在收到客户端时使用ID令牌,然后忽略之后的到期时间?

OpenID Connect specification只是说验证ID令牌时

"The current time MUST be before the time represented by the exp Claim."

(可能)支持上面的第三个选项。


修改

由于OpenID Connect建立在OAuth2上,下面的补充问题的答案可以在OAuth2 specification中找到,

expires_in
     RECOMMENDED.  The lifetime in seconds of the access token.

一个相关的问题是当您交换令牌的授权代码时,相同的规范说您可能会收到如下响应:

{
 "access_token": "SlAV32hkKG",
 "token_type": "Bearer",
 "refresh_token": "8xLOxBtZp8",
 "expires_in": 3600,
 "id_token": "eyJhbG[...]"
}

但是在这种情况下,“expires_in”与什么有关?访问令牌,刷新令牌或ID令牌?

(有关信息,IdentityServer3将此设置为访问令牌到期时间。

8 个答案:

答案 0 :(得分:68)

我回答了我自己的问题,因为我发现我的问题背后的一些假设是错误的,这里更容易澄清,而不是重写问题。

ID令牌用于向客户证明用户已经过身份验证,以及他们是谁。

当客户端收到ID令牌时,通常会执行将其转换为ClaimsIdentity的操作,并将其保留,例如使用cookie。

ID令牌必须在此使用点未到期(应该是,因为它刚刚发布)。但在此之后它不会再次使用,所以如果它到期时无关紧要,而用户仍有活动会话。客户端具有所需的身份验证信息,并且可以在用户必须再次登录之前选择自己的会话持续时间的策略。

我在提问时的错误假设是ID标记和访问令牌应该一起使用,因此两者都需要有效的到期日期。出于各种原因这是错误的:

  • ID令牌仅用于向客户端进行身份验证(如上所述)。
  • 访问令牌与客户无关。它们用于访问资源,而客户端只有在需要调用资源时才处理它们。
  • 像独立的MVC或WebForms应用程序之类的东西需要ID令牌。如果它没有调用外部资源,则没有任何内容可以授予访问权限,因此没有访问令牌。

答案 1 :(得分:27)

由于我自己的原因,我不得不深入研究这篇文章并写下来,所以我会发布我在这里学到的东西......

首先,我将回答这个问题,冒着明显的风险:如果当前时间大于过期时间,则无法信任ID令牌,并且必须忽略其内容。提问者的回答指出,在用户的初始认证之后,ID令牌不再被使用。但是,由于ID令牌是由身份提供商签名,因此它随时可以有用,以便可靠地确定用户对其他服务的用户应用可能正在使用。使用简单的用户ID或电子邮件地址不是可靠,因为它很容易被欺骗(任何人都可以发送电子邮件地址或用户ID),但由于OIDC ID令牌由授权服务器签名(它通常也有第三方的好处)它不能被欺骗,是一种更可靠的认证机制。

例如,移动应用可能希望能够告知后端服务用户正在使用该应用,并且可能需要在初始身份验证后的短暂时间段内执行此操作,此时ID令牌已过期,因此无法用于可靠地验证用户。

因此,就像访问令牌(用于授权 - 指定用户拥有的权限)可以刷新一样,可以刷新ID令牌(用于身份验证) - 指定谁是用户)?根据OIDC规范,答案并不明显。在OIDC / OAuth中,有三个用于获取令牌的“流”,授权码流,隐式流和混合流(我将在下面跳过,因为它是另外两个的变体)。

对于implicit flow in OIDC/OAuth,您在授权端点请求ID令牌,方法是将浏览器中的用户重定向到授权端点,并将id_token作为response_type请求参数的值。 Implicit Flow Successful Authentication Response必须包含id_token

对于the Authentication Code flow,客户端在将用户重定向到授权端点时将code指定为response_type请求参数的值。成功的响应包括授权代码。客户端客户端使用授权代码向令牌端点发出请求,并且根据OIDC Core Section 3.1.3.3 Successful Token Response ,响应必须包含ID令牌

因此,对于任何一种流程,这就是您最初获取ID令牌的方式,但是如何刷新它? OIDC Section 12: Using Refresh Tokens有关于刷新令牌响应的以下声明:

  

成功验证刷新令牌后,响应正文是3.1.3.3节的令牌响应,但它可能不包含id_token

可能不会包含ID令牌,并且由于无法指定强制它包含ID令牌,因此您必须假定响应不包含ID令牌。因此从技术上讲,没有指定的方法使用刷新令牌“刷新”ID令牌。因此,获取新ID令牌的唯一方法是通过将用户重定向到授权端点来重新授权/验证用户,并启动隐式流或身份验证代码流,如上所述。 OIDC规范确实向authorization request添加了prompt请求参数,因此客户端可以请求授权服务器不会使用任何UI提示用户,但重定向仍然具有发生。

答案 2 :(得分:5)

意图相同:在id_token过期后,您无法使用id_token。主要区别在于access_token是一种数据结构,您不需要调用任何服务器或端点,因为信息是在令牌本身中编码的。常规id_token通常是不透明的工件(如GUID)。

exp的消费者必须始终验证其(时间)有效性。

我不是100%熟悉IS,但我猜它是一个便利领域。您应该始终查看id_token声明。

  

到期只是其中一项验证。 {{1}}也经过数字签名,这也是必须执行的验证。

答案 3 :(得分:5)

如果我理解正确,根据thisOpenID Connect Core 1.0 spec,ID令牌本身可以存储在cookie中作为持久化会话的机制,并与每个需要身份验证的请求一起发送给客户端。然后,客户端可以在本地或通过提供商的验证者端点(如果提供,like Google does)验证ID令牌。如果令牌已过期,则应该发出另一个身份验证请求,但这次在URL参数中使用prompt=none。另外,请确保在id_token_hint参数中发送过期的ID令牌,否则提供商可能会返回错误。

因此,ID令牌过期似乎很自然,但prompt=none确保无需用户干预即可顺利获取新的ID令牌(除非用户注销该OpenID)。< / p>

答案 4 :(得分:4)

刷新令牌意味着您可以再次使用它来从授权服务器(在本例中为OP - OpenID-Connect提供程序)请求某些内容,即使用户未登录也是如此。您通常仅在有限资源的情况下允许此操作,并且仅在用户登录并至少进行一次身份验证后才允许此操作。刷新令牌本身也应该在时间上受到限制。

在OIDC 隐式流 中,您可以调用授权端点,
并在响应中接收ID令牌以及所有范围,并在其中接收所有索赔信息 对API的后续调用应使用 代码流 完成。
隐式流程旨在启用仅限JavaScript或仅限浏览器的应用程序。不是与服务器交互的应用程序 所以即使有办法去刷新&#34;这个标记,你不应该 - 安全明智 - 允许它活得太久。它会被未经授权的用户冒充并重新使用。您应该为此强制执行新登录。

代码流 中,您可以致电OP的授权终端,并收到 授权代码 (也称为授权令牌,或简称为authcode)。这应该类似于您在隐式流程中收到的id_token,出于同样的原因,不能也不应该续订。

您的用户界面或应用程序然后调用OP的令牌端点并接收(有时在用户通过UI进一步同意后允许在OP服务器上使用其拥有的资源)两个:

  • 用于身份验证的id_token - 在服务器调用中不应再次使用,除非在注销期间提示,当它的到期时间不再重要时,因此,由于上述原因应该让它过期,并且永远不会刷新。
  • access_token - 稍后在调用API时,可以将其提供给OP的UserInfo端点。这将返回声明,API可以相应地进行授权。

您可以刷新此access_token,因为它只告诉API用户拥有哪些声明,以及用户同意为您提供的资源(按作用域和每个范围的声明)。如上所述,这是为了即使在用户不再登录之后也允许访问。当然,您永远不希望允许刷新id_token,因为您不想在不登录的情况下允许模拟。

答案 5 :(得分:3)

我想将此答案作为评论发布,但由于我在StackOverflow上一直非常活跃,我想我会将其作为替代答案发布。

尝试将用户从会话http://openid.net/specs/openid-connect-session-1_0.html中注销时,您还可以使用id_token作为id_token_hint。老实说,如果id_token此时已过期,那我真的很重要,因为您只关心注销某个特定用户。

答案 6 :(得分:3)

TLDR;

在信任它所说的内容之前验证ID令牌。

更多详情

  

OpenID Connect中ID令牌到期时间的意图是什么?

目的是允许客户端验证ID令牌,客户端必须在使用ID令牌信息的操作之前验证ID令牌。

来自the OpenID Implicit Flow spec

  

如果本文档中定义的任何验证程序失败,则任何需要无法正确验证的信息的操作必须中止,并且不能使用无法验证的信息。

为了证实这一点,Google's OpenID Connect documentation说明了ID令牌验证:

  

使ID令牌变得有用的一点是,您可以将它们传递给应用的不同组件。这些组件可以使用ID令牌作为验证应用程序和用户的轻量级身份验证机制。 但在您可以使用ID令牌中的信息或依赖它作为用户已经过身份验证的断言之前,您必须对其进行验证。

因此,如果我们的客户端应用程序要根据ID令牌的内容采取某些操作,那么我们必须再次验证ID令牌。

答案 7 :(得分:0)

分享我的旅程。现在是 2021 年 6 月。我写这篇文章是因为我偶然发现了 3rd 方身份验证业务。我是一名资深程序员,但对安全是新手。换句话说,所有的标准、规范和术语都是陌生人,任何人都可以在这个领域打败我。请原谅我没有遵守所有条款。

切入正题,我正在编写一个 Angular/Node 应用程序,因此 UI=Angular,API(API 服务器)=Node/Express。我没有创建自己的用户名/密码身份验证,而是转向 3rd 方身份验证,让他们验证用户声称的真实性。这里有两本对我来说很重要的指南:

  1. Angular Authentication With JSON Web Tokens (JWT): The Complete Guide
  2. Eiji's Authenticate with a backend server

结合 1 号和 angularx-social-login,我将 UI 与 Google 连接起来,然后将 idToken 附加到 API,瞧!继No. 2 使用本地库API 可以验证idToken,太棒了!

等等,idTokenexp 将在 1 小时后过期。如何刷新?

我的理解是我只需要谷歌的身份验证,我不在乎他们使用什么标准和版本,但和其他人一样,我只相信他们的身份验证。 身份验证基本上验证他们声称的身份。 授权是对用户可以做什么/去哪里/去哪里的访问控制。内部访问控制(允许用户做什么)不会暴露给他们不知道的谷歌。所以 accessToken 应该不在图片中。对吗?

我花了几天时间研究如何刷新idToken,现在得出的结论是 Google 不推荐它,angularx-social-login 也没有提供任何方法。在第 2 项中,Eiji has stated clearlyenter image description here

因此,我的情况的解决方案是

  • 使用 Google 的身份验证。
  • 在初始验证 idToken 后在 API 中创建自己的会话管理/超时规则以减轻 exp
  • 最好使用 res.cookie("SESSIONID", myOwnID, {httpOnly:true, secure:true}); 将此会话数据添加到 cookie 中

为了更好的保护,Eiji 还推荐 Cross Account Protection。希望这会对某人有所帮助!