在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."
哪(可能)支持上面的第三个选项 .
EDIT
由于OpenID Connect Build 在OAuth2上,下面的补充问题的答案可以在_815428中找到,其中说,
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将此设置为访问令牌到期时间) .
7 回答
我正在回答我自己的问题,因为我发现我的问题背后的一些假设是错误的,这里更容易澄清,而不是重写问题 .
ID令牌用于向客户证明用户已经过身份验证,以及他们是谁 .
当客户端收到ID令牌时,通常会执行类似将其转换为ClaimsIdentity的操作,并将其保留,例如使用cookie .
ID令牌在这个使用点必须是未过期的(它应该是,因为它刚刚发布) . 但在此之后它不会再次使用,所以当用户仍然有一个活动会话时 it does not matter if it expires . 客户端具有所需的身份验证信息,并且可以选择自己的策略,以确定在用户必须再次登录之前会话持续多长时间 .
在提出问题时我的错误假设是ID标记和访问令牌应该一起使用,因此两者都需要有效的到期日期 . 出于各种原因这是错误的:
ID令牌仅用于向客户端进行身份验证(如上所述) .
访问令牌与客户端无关 . 它们用于访问资源,而客户端只在需要调用资源时才处理它们 .
像独立的MVC或WebForms应用程序这样的东西只需要一个ID令牌 . 如果它没有调用外部资源,则没有任何内容可以授予访问权限,因此没有访问令牌 .
我不得不因为我自己的原因深入研究并编写了这些内容,所以我将发布我在这里学到的内容......
首先,我回答说,在用户初始认证之后,ID令牌不再使用 . 但是,由于ID令牌由身份提供者签名,因此在任何时候提供一种可靠地确定用户对应用程序可能正在使用的其他服务的用户的方式肯定是有用的 . 使用简单的用户ID或电子邮件地址是不可靠的,因为它很容易被欺骗(任何人都可以发送电子邮件地址或用户ID),但由于OIDC ID令牌由授权服务器签署(通常也有作为第三方)它不能被欺骗,是一种更可靠的认证机制 .
例如,移动应用程序可能希望能够告诉后端服务用户是谁正在使用该应用程序,并且可能需要在初始身份验证之后的短暂时段之后执行此操作,此时ID令牌已过期,因此,不能用于可靠地验证用户 .
因此,就像访问令牌(用于授权 - 指定用户具有哪些权限)可以刷新一样, can you refresh the ID Token (用于身份验证 - 指定用户是谁)?根据OIDC规范,答案不是下面的,因为它是另外两个的变体 .
对于implicit flow in OIDC/OAuth,您通过将浏览器中的用户重定向到授权 endpoints 并包含
id_token
作为response_type
请求参数的值来请求授权 endpoints 处的ID令牌 . Implicit Flow Successful Authentication Response必须包含id_token
.对于the Authentication Code flow,客户端在将用户重定向到授权 endpoints 时将
code
指定为response_type
请求参数的值 . 成功的响应包括授权代码 . 客户端客户端使用授权代码向令牌 endpoints 发出请求,并且根据OIDC Core Section 3.1.3.3 Successful Token Response,响应必须包含ID令牌 .所以对于任何一个流程,这就是你最初获得ID令牌的方式,但是你如何刷新它? OIDC Section 12: Using Refresh Tokens有关于Refresh的以下声明令牌响应:
它 might not 包含一个ID令牌,因为没有指定强制它包含ID令牌的方法,你必须假设响应不包含ID令牌 . 因此从技术上讲,使用刷新令牌没有指定的方式来使用ID令牌 . 因此, the only way to get a new ID Token is to re-authorize/authenticate the user by redirecting the user to the authorization endpoint 并启动如上所述的隐式流或认证码流程 . OIDC规范确实向authorization request添加了一个
prompt
请求参数,因此客户端可以请求授权服务器不会使用任何UI提示用户,但重定向仍然必须发生 .这是相同的意图:在过期后你不能使用
id_token
. 主要区别在于id_token
是一种数据结构,您不需要调用任何服务器或 endpoints ,因为信息是在令牌本身中编码的 . 常规access_token
通常是不透明的工件(如GUID) .id_token
的消费者必须始终验证它的(时间)有效性 .我不是100%熟悉IS,但我猜它是一个便利领域 . 您应该始终检查
exp
索赔 .刷新令牌意味着您可以再次使用它来从授权服务器(在本例中为OP - OpenID-Connect提供程序)请求某些内容,即使用户未登录也是如此 . 您通常仅在有限资源的情况下允许此操作,并且仅在用户登录并至少进行一次身份验证后才允许此操作 . 刷新令牌本身也应该在时间上受到限制 .
在OIDC implicit flow 中,您调用授权 endpoints ,
并在响应中接收ID令牌以及所有范围,并在其中接收所有声明信息 .
对API的后续调用应使用 code flow 完成 .
隐式流程旨在启用仅限JavaScript或仅限浏览器的应用程序 . 不是与服务器交互的应用程序 .
所以,即使有一种方法来使用这个令牌,你也不应该 - 安全明智 - 让它活得太久 . 它会被未经授权的用户冒充并重新使用 . 你应该强制新的登录 .
在 code flow 中,您调用OP的授权 endpoints ,并接收 Authorization code (也称为授权令牌,或简称为authcode) . 这应该类似于您在隐式流中收到的id_token,出于同样的原因,不能也不应该续订 .
您的UI或应用程序然后调用OP的令牌 endpoints ,并接收(有时在用户通过UI进一步同意以允许在OP的服务器上使用其拥有的资源之后):
用于身份验证的id_token - 在服务器调用中不应再次使用,除非在注销期间提示,当它的到期时间不再重要时,因此,由于上述原因,应该让它过期,并且永远不会刷新 .
access_token - 稍后在调用API时,可以将其提供给OP的UserInfo endpoints . 这将返回声明,API可以相应地进行授权 .
您可以刷新此access_token,因为它只告诉API用户拥有哪些声明,以及用户同意为您提供哪些资源(按作用域和每个作用域的声明) . 如上所述,这是为了即使在用户不再登录之后也允许访问 . 当然,您永远不希望允许刷新id_token,因为您不希望在不登录的情况下允许模拟 .
我想把这个答案作为评论发布,但由于我在StackOverflow上没有非常活跃,我想我会把它作为替代答案发布 .
尝试将用户从会话http://openid.net/specs/openid-connect-session-1_0.html中注销时,也使用
id_token
作为id_token_hint
. 老实说,如果id_token
此时已过期,我认为这并不重要,因为您只关心注销特定用户 .如果我理解正确,根据this和OpenID Connect Core 1.0 spec,ID令牌本身可以存储在cookie中作为持久化会话的机制,并与每个需要身份验证的请求一起发送给客户端 . 然后,客户端可以在本地或通过提供商的验证者 endpoints (如果提供,like Google does)验证ID令牌 . 如果令牌已过期,则应该发出另一个auth请求,但这次使用URL参数中的
prompt=none
除外 . 还要确保在id_token_hint
参数中发送过期的ID令牌,否则Provider可能会返回错误 .因此,ID令牌过期似乎很自然,但
prompt=none
确保无需用户干预即可顺利获取新的ID令牌(当然除非用户从该OpenID注销) .TLDR;
在信任它所说的内容之前验证ID令牌 .
更多细节
目的是允许客户端验证ID令牌,客户端必须 validate the ID token before operations that use the ID token's information .
来自the OpenID Implicit Flow spec:
为了证实这一点,Google's OpenID Connect documentation说这是关于ID令牌验证的:
因此,如果我们的客户端应用程序要根据ID令牌的内容采取某些操作,那么我们必须再次验证ID令牌 .