105

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

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

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

你的意思是:

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

OpenID Connect 规范只是说在验证 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将其设置为访问令牌到期时间)。

4

8 回答 8

109

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

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

当客户端收到一个 ID 令牌时,它通常会做一些事情,比如将其转换为 ClaimsIdentity,并保持它,例如使用 cookie。

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

当我问这个问题时,我的错误假设是 ID 令牌和访问令牌应该一起使用,因此两者都需要有有效的到期日期。这是错误的,原因有很多:

  • ID 令牌仅用于向客户端进行身份验证(如上所述)。
  • 访问令牌与客户端无关。它们用于访问资源,客户端仅在需要调用资源时才处理它们。
  • 像独立的 MVC 或 WebForms 应用程序需要一个 ID 令牌。如果它没有调用外部资源,则没有可以授予访问权限的内容,因此没有访问令牌。
于 2014-09-12T14:14:15.967 回答
45

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

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

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

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

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

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

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

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

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

于 2015-10-30T19:32:26.620 回答
10

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

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

于 2016-08-23T15:15:31.047 回答
6

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

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

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

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

于 2014-09-06T00:55:54.647 回答
6

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

在 OIDC隐式流程中,您调用授权端点,
并在响应中接收 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,因为您不想在不登录的情况下允许模拟。

于 2015-11-21T23:26:53.033 回答
4

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

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

于 2015-05-18T22:41:55.457 回答
4

TLDR;

在相信它所说的之前验证 ID 令牌。

更多细节

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

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

OpenID 隐式流规范

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

为了证实这一点,Google 的 OpenID Connect 文档对 ID 令牌验证进行了说明:

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

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

于 2016-11-16T00:20:22.547 回答
0

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

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

  1. 使用 JSON Web 令牌 (JWT) 的 Angular 身份验证:完整指南
  2. Eiji 使用后端服务器进行身份验证

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

等等,idToken1exp小时后过期。我该如何刷新它?

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

我花了几天时间研究如何刷新idToken现在得出的结论是谷歌不推荐它也不angularx-social-login提供方法。在第 2 期中,Eiji 明确表示在此处输入图像描述

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

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

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

于 2021-06-18T18:18:22.953 回答