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

App*_*ere 79 oauth-2.0 openid-connect

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

该ID令牌还具有期满时间.我的问题是这是什么意思?

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

所以你的意思是:

  • 为您的ID令牌提供比刷新令牌到期更长的时间,或者
  • 将它设置为与访问令牌相同的到期时间并在其到期时执行某些操作(什么?),或者
  • 只是在收到时在客户端使用ID令牌,然后忽略之后的到期时间?

该ID连接规范只是说,验证一个ID令牌时,

"The current time MUST be before the time represented by the exp Claim."
Run Code Online (Sandbox Code Playgroud)

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


编辑

由于OpenID Connect建立在OAuth2上,因此可以在OAuth2规范中找到以下补充问题的答案,该规范说,

expires_in
     RECOMMENDED.  The lifetime in seconds of the access token.
Run Code Online (Sandbox Code Playgroud)

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

{
 "access_token": "SlAV32hkKG",
 "token_type": "Bearer",
 "refresh_token": "8xLOxBtZp8",
 "expires_in": 3600,
 "id_token": "eyJhbG[...]"
}
Run Code Online (Sandbox Code Playgroud)

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

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

App*_*ere 75

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

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

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

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

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

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

  • 在扩展其到期时,您无法刷新ID令牌(通过使用脱机访问令牌可以刷新访问令牌).但是如果你有一个与OpenID Connect Provider的未过期认证会话(例如登录IdentityServer3后的cookie),那么当你重复登录请求时,提供商可以跳过身份验证(因为cookie说你已经完成了)并且只返回一个新的ID令牌(如果请求,则为访问令牌).只有当cookie的生命周期比ID令牌更长时,这才有效. (6认同)
  • 你对此有什么参考吗?Eugenio声称你可以在他的答案中刷新一个id令牌.这是真的? (3认同)
  • 您可以编辑您的答案吗,因为您没有真正解释 Id 令牌过期的目的,您只是说当您有活动会话时这并不重要(这是正确的)。我的猜测是,Id 令牌过期的目的是防止重放攻击。如果有人记录来自身份验证服务器的流量,那么他可以使用记录的流量来欺骗客户端应用程序,让其相信他拥有有效的用户身份。但如果客户端检查到期日期,它会发现这可能是重播攻击。(随机数用于相同目的)。 (3认同)

Sco*_*eke 29

我不得不因为我自己的原因深入研究这个问题并写下来,所以我将发布我在这里学到的东西......

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

例如,移动应用程序可能希望能够告诉后端服务用户是谁正在使用该应用程序,并且可能需要在初始身份验证之后的短暂时段之后执行此操作,此时ID令牌已过期,因此,不能用于可靠地验证用户.

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

对于OIDC/OAuth中的隐式流,您可以通过将浏览器中的用户重定向到授权端点并包含id_token作为response_type请求参数的值来在授权端点请求ID令牌.需要隐式流成功的身份验证响应以包含id_token.

对于身份验证代码流,客户端在将用户重定向到授权端点时指定code为response_type请求参数的值.成功的响应包括授权代码.客户端客户端使用授权代码向令牌端点发出请求,并且根据OIDC核心部分3.1.3.3成功令牌响应 ,响应必须包括ID令牌.

所以对于任何一个流程,这就是你最初获得ID令牌的方式,但是你如何刷新它?OIDC第12节:使用刷新令牌有关于刷新令牌响应的以下声明:

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

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


Mor*_*ess 7

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

因此,ID令牌过期似乎很自然,但prompt=none可以确保在没有用户干预的情况下顺利获取新的ID令牌(除非用户退出该OpenID)。


pas*_*ute 6

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

在 OIDC隐式流中,您调用 Authorization 端点,
并在响应中接收 ID 令牌以及所有范围和所有声明信息。
对 API 的后续调用旨在通过代码流完成。
隐式流旨在启用仅 javascript 或仅浏览器的应用程序。不是与服务器交互的应用程序。
所以即使有办法“刷新”这个令牌,你也不应该 - 安全明智 - 让它存活太久。它将被冒充该 ID 的未经授权的用户窃取和重用。您应该为此强制进行新的登录。

在代码流中,您调用 OP 的授权端点,并接收授权代码(也称为授权令牌,或简称为 authcode)。这应该与您在隐式流中收到的 id_token 类似,出于相同的原因,并且不能也不应该更新。

然后您的 UI 或应用程序调用 OP 的 Token 端点,并接收(有时在用户通过 UI 进一步同意以允许在 OP 的服务器上使用他们拥有的资源之后):

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

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

  • 你所说的关于隐式流的部分是不正确的。除了 ID 令牌之外,使用隐式流的客户端还可以获得访问令牌,并且可以使用该访问令牌与服务器交互。 (2认同)

Eug*_*ace 5

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

消费者id_token必须始终验证它的(时间)有效性.

我不是100%熟悉IS,但我猜它是一个便利领域.你应该经常检查exp索赔.

到期只是验证之一.id_tokens也经过数字签名,这也是您必须执行的验证.

  • 谢谢尤金尼奥。我的主要问题是当 ID 令牌过期时您应该做什么?我认为(可能是错误的)要更新短期访问令牌,您必须使用刷新令牌。但是,如果 ID 令牌与访问令牌具有相同的有效期,您将立即拥有过期的 ID 令牌,因此刷新访问令牌似乎毫无意义。我想我可能在这里遗漏了一些东西! (2认同)
  • 我的最新理解是,当用户与授权服务器进行经过身份验证的会话时,当访问令牌到期时,401 => 302重定向到授权服务器将获得新的访问和ID令牌,而无需用户干预.但是在离线模式下,refresh_token将仅返回一个新的access_token,表示允许特定用户访问某些资源.它不能返回id_token,因为它会说特定用户已经过身份验证,而在离线模式下则不是这样. (2认同)

小智 5

我想将此答案作为评论发布,但由于我在 StackOverflow 上不是很活跃,所以我想我将其发布为替代答案。

id_token当id_token_hint尝试将用户从会话中注销时,您还可以使用http://openid.net/specs/openid-connect-session-1_0.html。老实说,我认为此时是否过期并不重要,id_token因为您只关心注销特定用户。