OAuth 2.0协议草案的第4.2节指出,授权服务器可以返回access_token(用于通过资源验证自己)和refresh_token,refresh_taken纯粹用于创建新的access_token:

https://www.rfc-editor.org/rfc/rfc6749#section-4.2

为什么两者都有?为什么不让access_token和refresh_token一样长,而不设置refresh_taken?


当前回答

而刷新令牌由授权服务器保留。访问令牌是自包含的,因此资源服务器可以在不存储它的情况下对其进行验证,从而节省了验证时的检索工作。讨论中缺少的另一点来自rfc6749#page-55

“例如,授权服务器可以使用刷新令牌每次访问都会发出新的刷新令牌的循环令牌刷新响应。上一个刷新令牌无效,但由授权服务器保留。如果刷新令牌为攻击者和合法客户端,其中一个将显示无效的刷新令牌,该令牌将通知授权服务器违规。"

我认为使用刷新令牌的关键在于,即使攻击者设法获得了刷新令牌、客户端ID和秘密组合。如果每次刷新请求都会产生新的访问令牌和刷新令牌,则可以通过后续调用从攻击者处获取新的访问标志。

其他回答

这一切都与扩展和保持资源服务器无状态有关。

您的服务器/资源服务器服务器是无状态的,这意味着不检查任何存储以快速响应。通过使用公钥验证令牌的签名来执行此操作。检查每个请求的access_token。通过只检查access_token的签名和过期日期,响应速度非常快,并允许扩展。access_token应该有很短的到期时间(几分钟),因为如果它被泄露,就没有办法撤销它。身份验证服务器/OAuth服务器服务器不是无状态的,但它可以,因为请求要少得多。仅在access_token过期时检查refresh_token。(例如每2分钟)请求速率远低于资源服务器。将刷新令牌存储在数据库中,并可以撤消它。refresh_token可能有很长的到期时间(几周/几个月),如果它被泄露,有办法撤销它。

不过有一个重要的注意事项,身份验证服务器的请求要少得多,因此可以处理负载,但是由于必须存储所有refresh_token,因此可能存在存储问题,如果用户急剧增加,这可能会成为一个问题。

而刷新令牌由授权服务器保留。访问令牌是自包含的,因此资源服务器可以在不存储它的情况下对其进行验证,从而节省了验证时的检索工作。讨论中缺少的另一点来自rfc6749#page-55

“例如,授权服务器可以使用刷新令牌每次访问都会发出新的刷新令牌的循环令牌刷新响应。上一个刷新令牌无效,但由授权服务器保留。如果刷新令牌为攻击者和合法客户端,其中一个将显示无效的刷新令牌,该令牌将通知授权服务器违规。"

我认为使用刷新令牌的关键在于,即使攻击者设法获得了刷新令牌、客户端ID和秘密组合。如果每次刷新请求都会产生新的访问令牌和刷新令牌,则可以通过后续调用从攻击者处获取新的访问标志。

我在这里获得了一些额外的资源,这些资源澄清了我们为什么需要refresh_token的某些问题。这些资源的一些要点如下:

在现实世界中,最好使用名为authServer和resourceServer/s的独立服务器authServer-仅用于身份验证和授权。该服务器的职责是发布刷新令牌、访问令牌以及登录和注销用户resourceServer-此服务器(也可以是负载平衡的多个服务器)提供受保护的数据。例如,这些数据可以像电子商务项目中的产品、评论等refresh_token的一个用途是,每次需要新的access_token时,我们不必通过网络(从前端到authServer)发送用户名和密码(凭据)。这应该只在第一次完成(当您还没有refresh_token时),refresh_taken将立即从authServer获取新的access_token,这样您就可以继续向受保护的resourceServer发出请求。这里的优点是,用户不必每次都提供凭据,因此用户的用户名和密码不容易被泄露。refresh_token的另一个主要用途是,假设您的authServer与现实世界中的resourceServer(第三方服务,如auth0、okta、azure等,或您自己的实现)相比非常受保护。您只需将access_token发送到resourceServer(以获取数据),而无需向resourceServer发送refresh_token。因此,当您的access_token发送到resourceServer时,很有可能会有黑客拦截您的resourceServer(因为它不像authServer那样安全),从而访问您的短暂访问权。因此,access_token的寿命很短(例如30分钟)。记住,当这个access_token过期时,您将向authServer(它比resourceServer更安全)发送refresh_token以获取新的access_toke。由于您在任何时候都不会向resourceServer发送refresh_token,因此拦截resourceServer的黑客不可能获得您的refresh_taken。如果作为一名开发人员,您仍然怀疑用户的refresh_token也可能被黑客入侵,那么您可以注销所有用户(使refresh_taken对所有用户无效),这样用户将再次登录(提供用户名和密码)以获得新的refresh_token+access_token,事情将再次步入正轨。

一些有用的资源

具有或不具有刷新令牌的工作流-Youtube

JWT认证代码示例-节点JS-Youtube

据我所知,如果您需要撤销访问,刷新令牌只是为了性能和成本节省。

例1:不实现刷新令牌;仅实现长期访问令牌:如果用户滥用服务(例如:不支付订阅),您需要能够撤销访问令牌=>您需要在每个需要访问令牌的API调用上检查访问令牌的有效性,这会很慢,因为它需要DB查找(缓存可以帮助,但这更复杂)。

例2:实现刷新令牌和短期访问令牌:如果用户滥用服务(例如:不支付订阅),您需要能够撤销访问令牌=>短暂的访问令牌将在短暂的白色(例如1小时)后过期,用户将需要获得新的访问令牌,因此我们不需要对需要访问令牌的每个API调用进行验证。您只需要在从刷新令牌生成访问令牌时验证用户。对于坏用户,如果无法生成访问令牌,则可以注销该用户。当用户尝试重新登录时,验证将再次运行并返回错误。

首先,客户端通过给予授权授权与授权服务器进行身份验证。然后,客户端通过提供访问令牌向资源服务器请求受保护的资源。资源服务器验证访问令牌并提供受保护的资源。客户端通过授予访问令牌向资源服务器发出受保护的资源请求,如果有效,资源服务器将在其中验证该请求并为请求提供服务。此步骤一直重复,直到访问令牌过期。如果访问令牌过期,则客户端向授权服务器进行身份验证,并通过提供刷新令牌来请求新的访问令牌。如果访问令牌无效,资源服务器将向客户端发回无效令牌错误响应。客户端通过授予刷新令牌与授权服务器进行身份验证。然后,授权服务器通过验证客户端来验证刷新令牌,并发出新的访问令牌(如果有效)。