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?


当前回答

客户可以通过多种方式受到损害。例如,可以克隆手机。访问令牌过期意味着客户端被迫重新向授权服务器进行身份验证。在重新认证期间,授权服务器可以检查其他特征(IOW执行自适应访问管理)。

刷新令牌允许仅客户端进行重新身份验证,其中重新授权会强制与用户进行对话,许多用户表示他们不愿意这样做。

刷新令牌基本上适用于正常网站可能选择在一小时左右后定期重新验证用户的相同位置(例如银行网站)。由于大多数社交网站都不会重新验证网络用户,因此目前它的使用率并不高,那么他们为什么要重新验证客户端呢?

其他回答

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

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

这个答案是在两位高级开发人员(约翰·布莱顿和大卫·詹内斯)的帮助下得出的。

使用刷新令牌的主要原因是减少攻击面。

假设没有刷新键,让我们来看看这个示例:

一座大楼有80扇门。所有车门都用同一把钥匙打开。钥匙每30分钟更换一次。在30分钟结束时,我必须把旧钥匙交给钥匙制造商,并获得一把新钥匙。

如果我是黑客,拿到了你的钥匙,那么在30分钟结束后,我会把它快递给钥匙制造商,并获得一把新钥匙。无论换钥匙,我都能连续打开所有车门。

问:在这30分钟里,我有多少次破解钥匙的机会?每次你使用密钥时,我都有80次黑客攻击的机会(把这看作是发出网络请求并传递访问令牌以识别自己)。这是80倍的攻击面。

现在让我们来看看同一个例子,但这次我们假设有一个刷新键。

一座大楼有80扇门。所有车门都用同一把钥匙打开。钥匙每30分钟更换一次。要获取新密钥,我无法传递旧的访问令牌。我只能通过刷新键。

如果我是黑客并得到了你的密钥,我可以使用它30分钟,但在30分钟结束时,将它发送给密钥制作者没有任何价值。如果我这样做了,那么密钥制作者只会说“此令牌已过期。您需要刷新令牌。”为了能够扩展我的黑客攻击,我必须将信使黑客攻击给密钥制作者。信使有一个不同的密钥(将其视为刷新令牌)。

问题:在30分钟内,我有多少次违反刷新键的黑客攻击机会?80? 不,我只有一次黑客攻击机会。在这段时间里,快递员与钥匙制造商进行沟通。这是1X攻击面。我确实有80次破解钥匙的机会,但30分钟后就不行了。


服务器将根据凭证和JWT的签名(通常)验证访问令牌。

访问令牌泄漏是不好的,但一旦过期,它对攻击者不再有用。刷新令牌泄漏的情况要糟糕得多,但估计可能性较小。(我认为,刷新令牌泄漏的可能性是否比访问令牌泄漏的概率低得多,这是一个问题,但这就是想法。)

重点是访问令牌被添加到您发出的每个请求中,而刷新令牌仅在刷新流期间使用所以MITM看到代币的可能性很小

频率有助于攻击者。像SSL中的潜在安全漏洞、客户端中的潜在的安全漏洞以及服务器中潜在的安全缺陷等令人心碎的漏洞都使泄漏成为可能。

此外,如果授权服务器与处理其他客户端请求的应用服务器分离,那么该应用服务器将永远不会看到刷新令牌。它只会看到不会持续很久的访问令牌。

分隔有利于安全。

最后但并非最不重要的刷新令牌可以被旋转。意思是“每次客户端请求将刷新令牌交换为新的访问令牌时,都会返回新的刷新令牌”。随着刷新令牌的不断交换和失效,威胁降低。举个例子:令牌通常在TTL之后过期,通常是一小时。

刷新令牌并不总是,但通常会在使用时被撤销,并发出新的令牌。这意味着,如果您在检索新的刷新令牌时发生网络故障,那么下次发送该刷新令牌时,它将被视为已吊销,您必须登录。

有关旋转的更多信息,请参阅此处和此处

总结

降低频率分区令牌的轮换(更快的失效)和更精细的管理(过期时间或请求数量)。

所有这些都有助于减轻威胁

关于这个问题的另一个观点,请看这个令人敬畏的答案


刷新令牌与什么无关?

通过刷新令牌更新/撤销访问级别的能力是选择使用刷新令牌的一个副产品,否则独立访问令牌可能会被撤销,或在其过期时修改其访问级别,用户将获得新令牌

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

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

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

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

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

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

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

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

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

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

让我们考虑一个系统,其中每个用户链接到一个或多个角色,每个角色链接到一种或多种访问权限。可以缓存这些信息以获得更好的API性能。但是,用户和角色配置可能会发生变化(例如,可能会授予新的访问权限,或者可能会撤销当前的访问权限),这些都应该反映在缓存中。

我们可以为此目的使用访问和刷新令牌。当使用访问令牌调用API时,资源服务器检查缓存的访问权限。如果有任何新的访问许可,则不会立即反映。一旦访问令牌过期(例如在30分钟内)并且客户端使用刷新令牌生成新的访问令牌,就可以使用来自DB的更新的用户访问权限信息来更新缓存。

换句话说,我们可以将昂贵的操作从使用访问令牌的每次API调用转移到使用刷新令牌生成访问令牌的事件。