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?


当前回答

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

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

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

其他回答

假设您使access_token持续很长时间,并且没有refresh_token,那么在一天之内,黑客就可以访问所有受保护的资源!

但如果你有refresh_token,access_token的生存时间很短,所以黑客很难破解你的access_toke,因为它在短时间后将无效。Access_token只能通过不仅使用refresh_token,而且还可以通过client_id和client_secret(黑客没有)检索回来。

这些答案都没有找到刷新令牌存在的核心原因。显然,您总是可以通过将客户端凭据发送到身份验证服务器来获得新的访问令牌/刷新令牌对——这就是您首先获得它们的方式。

因此,刷新令牌的唯一目的是限制通过网络发送到身份验证服务的客户端凭据的使用。访问令牌的TTL越短,就越需要使用客户端凭据来获取新的访问令牌,因此攻击者就越有机会破坏客户端凭据(尽管如果使用非对称加密发送客户端凭据,这可能非常困难)。因此,如果您有一个一次性刷新令牌,您可以使访问令牌的TTL任意小,而不影响客户端凭据。

刷新令牌的思想是,如果访问令牌因其短暂而受到破坏,攻击者可以在有限的窗口中滥用它。

刷新令牌(如果被破坏)是无用的,因为攻击者除了需要刷新令牌之外还需要客户端id和密码,以便获得访问令牌。

话虽如此,由于每次对授权服务器和资源服务器的调用都是通过SSL完成的,包括请求访问/刷新令牌时的原始客户端id和secret,因此我不确定访问令牌如何比长期刷新令牌和客户端id/secret组合更“不可妥协”。

当然,这与不同时控制授权服务器和资源服务器的实现不同。

这里有一个很好的线程,讨论了刷新令牌的使用:OAuth存档。

引用上述内容,讨论刷新令牌的安全目的:

刷新令牌。。。降低长期access_token泄漏的风险(在不安全的资源服务器上的日志文件中查询参数,测试版或编码不良的资源服务器应用程序,非https站点上的JS SDK客户端将access_toke放入cookie等)

我在这里获得了一些额外的资源,这些资源澄清了我们为什么需要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

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