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


92

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

令牌ID也有一个到期时间。我的问题是这个目的是什么?

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

因此,您是否打算:

  • 赋予您的ID令牌有效期比刷新令牌的有效期长,或者
  • 将其设置为与访问令牌相同的到期时间,并在到期时采取一些措施(做什么?),或者
  • 只是在收据时在客户中使用ID令牌,然后忽略此后的到期时间?

ID连接规范只是说,当验证ID令牌,

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

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


编辑

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

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将此设置为访问令牌的到期时间)。

Answers:


90

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

ID令牌用于向客户端证明用户已通过身份验证,以及身份证明。

当客户收到ID令牌时,通常会执行类似将其转换为ClaimsIdentity的操作,并例如使用cookie对其进行持久化。

在使用时,ID令牌必须永不过期(应该是有效的,因为它刚刚被发行)。但是此后不再使用,因此过期也没关系在用户仍具有活动会话的情况下。客户端具有所需的身份验证信息,然后可以选择自己的策略来确定会话在用户必须再次登录之前的持续时间。

在问这个问题时,我的错误假设是ID令牌和访问令牌应一起使用,因此两者都必须具有有效的到期日期。由于多种原因,这是错误的:

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

3
您对此有任何参考吗?Eugenio声称您可以在他的回答中刷新一个id令牌。这是真的?
AndyD

6
从扩展ID过期的意义上讲,您无法刷新ID令牌(通过使用脱机访问令牌可以刷新访问令牌的方式)。但是,如果您与OpenID Connect Provider的身份验证会话未到期(例如,登录IdentityServer3后的cookie),则当您重复登录请求时,Provider可以跳过身份验证(因为cookie表示您已完成身份验证)并仅返回一个新的ID令牌(如果需要,则带有&令牌)。当然,这仅在Cookie的生存期比ID令牌长的情况下才有效。
Appetere

1
虽然您可以这样做,但是我不确定这样做是否正确。对于最终用户来说,它也不是无缝的,因为它将需要少量的浏览器重定向。
Kir

@Kir如果您使用的是Javascript单页应用程序(SPA),则首次尝试更新通行证令牌通常是一个后台进程,因此最终用户不会受到干扰。例如,如果资源的API响应访问令牌已过期,则SPA向身份服务器发出后台请求,以获取新的访问令牌。仅当此操作失败(因为ID令牌已过期)时,才需要要求用户再次登录。有关示例代码,请参见github.com/IdentityServer/IdentityServer3.Samples/tree/master/…上的JavascriptImplicitClient示例。
Appetere

如果OIdC提供程序支持从Refresh_token请求返回它,则可以刷新Id_token。见stackoverflow.com/questions/41168304/...stackoverflow.com/questions/41741982/...
迈克尔Freidgeim

35

我出于自己的原因必须对此进行深入研究并将其写下来,因此我将在这里发布我学到的东西...

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

例如,移动应用可能希望能够告诉后端服务的用户正在使用该应用程序,它可能需要一小段时间,初始认证之后,此时的ID令牌过期后这样做,因此,不能用于可靠地验证用户身份。

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

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

对于Authentication Code流,客户端将用户重定向到授权端点时指定coderesponse_typerequest参数的值。成功的响应包括授权码。根据OIDC核心第3.1.3.3节“成功的令牌响应”,客户端客户端使用授权码向令牌端点发出请求。 ,响应必须包含一个ID令牌

因此,对于任一流程,这都是您最初获取ID令牌的方式,但是如何刷新它呢? OIDC第12节:使用刷新令牌具有以下有关刷新令牌响应的声明:

成功验证刷新令牌后,响应主体为第3.1.3.3节的令牌响应,但以下内容除外: 其中可能不包含id_token

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


如果要编写与任意授权提供程序一起使用的通用软件,则不能依赖于从刷新返回id_token。但是,如果您正在使用特定的提供程序(例如IdentityServer4),则可以检查其功能,并使用刷新请求后收到的id_token
Michael Freidgeim

那么,如何刷新id_token?
jwilleke '17

@jwilleke AFAIK,如上所述,“获取新ID令牌的唯一方法是通过将用户重定向到授权端点来重新授权/身份验证用户”
Scott Willeke

@MichaelFreidgeim有趣,您是说通过“开放ID连接发现”机制吗?我们到底该怎么做?
Scott Willeke

@ScottWilleke,我不确定是否被发现暴露了。我正在使用特定的提供程序IdentityServer4,并且从我知道的文档中得知,id_token是从刷新返回的。您可以在代码中检查代码是否返回,如果没有返回,请执行一些回退。
Michael Freidgeim

7

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

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


6

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

使用者id_token必须始终验证其(时间)有效性。

我不是100%熟悉IS,但我想这是一个便利领域。您应该始终检查exp索赔。

到期只是验证之一。id_token还会进行数字签名,这也是您必须执行的验证。


谢谢Eugenio。我的主要问题是,当ID令牌过期时应该怎么办?我认为(可能是错误的)要让您的HAD短暂使用访问令牌,以使用刷新令牌。但是,如果ID令牌与访问令牌具有相同的到期时间,您将立即拥有一个过期的ID令牌,因此刷新访问令牌似乎毫无意义。认为我可能在这里错过了一些东西!
听话

1
您将使用(未吊销)refresh_token获取新的access_token或id_token。或者只是作为用户再次登录。id_tokens在逻辑上等效于access_tokens。只是一种不同的格式。
Eugenio Pace 2014年

2
我的最新理解是,当用户与授权服务器进行身份验证的会话时,如果访问令牌到期,则401 => 302重定向到授权服务器将获得新的访问和ID令牌,而无需用户干预。但是在离线模式下,refresh_token将仅返回一个新的access_token,表示允许特定用户访问某些资源。它无法返回id_token,这意味着特定用户已通过身份验证,并且不是在离线模式下。
2014年

这将是有关id_token和access_token之间有什么区别的问题的一个很好的答案(尤其是在使用不透明/引用令牌时)。首先专注于回答问题,然后说明如何使用访问令牌和ID令牌?
特伦特

5

刷新令牌意味着即使用户未登录,也可以再次使用它来向授权服务器(在本例中为OP-OpenID-Connect Provider)请求请求。通常,仅在用户登录并经过至少一次身份验证之后,才仅允许有限的资源使用此功能。刷新令牌本身也应受时间限制。

在OIDC隐式流中,您调用授权端点,
并在响应中接收ID令牌以及所有范围以及其中的所有声明信息。
后续对API的调用应通过代码流完成
隐式流程旨在启用仅JavaScript或仅浏览器的应用程序。不是与服务器交互的应用程序。
因此,即使有一种方法可以“刷新”此令牌,但出于安全考虑,也不应允许其寿命太长。冒充该ID的未授权用户将窃取并重新使用它。您应该为此强制新的登录。

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

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

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

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


2
您对隐式流的说法部分不正确。使用隐式流的客户端不仅可以获取ID令牌,还可以获取访问令牌,并且可以使用该访问令牌与服务器进行交互。
Shaun Luttin

一种常见的做法是,当id_token过期时,客户端从服务器请求新的令牌,因此用户无需再次授权。例如,见damienbod.com/2017/06/02/...
迈克尔Freidgeim

4

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

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


4

TLDR;

信任ID令牌之前,请先对其进行验证。

更多细节

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

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

根据OpenID隐式流规范

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

为了证实这一点,Google的OpenID Connect文档说明了有关ID令牌验证的内容:

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

因此,如果我们的客户端应用程序将基于ID令牌的内容采取某些措施,则我们必须再次验证ID令牌。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.