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?
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和refresh_token一样长不吃点心吗?
除了其他人提供的出色答案之外,我们使用刷新令牌还有另一个原因,这与声明有关。
每个令牌都包含声明,这些声明可以包括用户名、用户角色或创建声明的提供者等任何内容。当刷新令牌时,这些声明将被更新。
如果我们更频繁地刷新令牌,显然会给我们的身份服务带来更大的压力;然而,我们正在获得更准确和最新的声明。
其他回答
Catchdave提供的讨论链接还有Dick Hardt提出的另一个有效的观点(原始的,死链接),我认为除了上面写的内容之外,这里还值得一提:
我记得刷新令牌是为了安全和撤销。<...>撤销:如果访问令牌是自包含的,则可以通过不发布新的访问令牌来撤销授权。资源不需要查询授权服务器以查看访问令牌是否有效。这简化了访问令牌验证,并使扩展和支持多个授权服务器更加容易。当访问令牌有效但授权被撤销时,有一个时间窗口。
事实上,在资源服务器和授权服务器是同一个实体的情况下,并且用户和其中任何一个之间的连接(通常)都是同样安全的,那么将刷新令牌与访问令牌分开并没有多大意义。
尽管如引用中所述,刷新令牌的另一个作用是确保用户可以随时(例如通过其配置文件中的web界面)撤销访问令牌,同时保持系统的可伸缩性。
通常,令牌可以是指向服务器数据库中特定记录的随机标识符,也可以包含自身的所有信息(当然,这些信息必须使用MAC进行签名)。
具有长期访问令牌的系统应该如何工作
服务器允许客户端通过发出令牌访问预定义范围内的用户数据。由于我们希望保持令牌的可撤销性,我们必须在数据库中存储令牌以及设置或取消设置的标志“已撤销”(否则,如何使用自包含令牌?)。数据库可以包含多达len(用户)x len(注册客户端)x len(范围组合)的记录。然后,每个API请求都必须命中数据库。虽然对执行O(1)的数据库进行查询非常简单,但单点故障本身可能会对系统的可伸缩性和性能产生负面影响。
具有长期刷新令牌和短期访问令牌的系统应该如何工作
在这里,我们发布两个密钥:带有数据库中相应记录的随机刷新令牌,以及签名的自包含访问令牌,其中包含过期时间戳字段。
由于访问令牌是自包含的,因此我们根本不必访问数据库来检查其有效性。我们所要做的就是解码令牌并验证签名和时间戳。
尽管如此,我们仍然需要保留刷新令牌的数据库,但对该数据库的请求数量通常由访问令牌的寿命定义(寿命越长,访问率越低)。
为了撤销特定用户对客户端的访问,我们应该将相应的刷新令牌标记为“已撤销”(或完全删除),并停止发布新的访问令牌。很明显,在一个窗口中,刷新令牌已被撤销,但其访问令牌可能仍然有效。
权衡取舍
刷新令牌部分消除了访问令牌数据库的SPoF(单点故障),但它们有一些明显的缺点。
“窗口”。事件“用户撤销访问”和“保证撤销访问”之间的时间间隔。客户端逻辑的复杂性。无刷新令牌使用访问令牌发送API请求如果访问令牌无效,则失败并要求用户重新验证带刷新令牌使用访问令牌发送API请求如果访问令牌无效,请尝试使用刷新令牌更新它如果刷新请求通过,则更新访问令牌并重新发送初始API请求如果刷新请求失败,请要求用户重新验证
我希望这个答案确实有意义,有助于某人做出更深思熟虑的决定。我还想指出,一些著名的OAuth2提供商,包括github和foursquare,采用了没有刷新令牌的协议,并对此感到满意。
刷新令牌的思想是,如果访问令牌因其短暂而受到破坏,攻击者可以在有限的窗口中滥用它。
刷新令牌(如果被破坏)是无用的,因为攻击者除了需要刷新令牌之外还需要客户端id和密码,以便获得访问令牌。
话虽如此,由于每次对授权服务器和资源服务器的调用都是通过SSL完成的,包括请求访问/刷新令牌时的原始客户端id和secret,因此我不确定访问令牌如何比长期刷新令牌和客户端id/secret组合更“不可妥协”。
当然,这与不同时控制授权服务器和资源服务器的实现不同。
这里有一个很好的线程,讨论了刷新令牌的使用:OAuth存档。
引用上述内容,讨论刷新令牌的安全目的:
刷新令牌。。。降低长期access_token泄漏的风险(在不安全的资源服务器上的日志文件中查询参数,测试版或编码不良的资源服务器应用程序,非https站点上的JS SDK客户端将access_toke放入cookie等)
为了进一步简化B T的答案:当您通常不希望用户再次输入凭据,但仍然希望能够撤销权限(通过撤销刷新令牌)时,请使用刷新令牌
您不能撤销访问令牌,只能撤销刷新令牌。
让我们考虑一个系统,其中每个用户链接到一个或多个角色,每个角色链接到一种或多种访问权限。可以缓存这些信息以获得更好的API性能。但是,用户和角色配置可能会发生变化(例如,可能会授予新的访问权限,或者可能会撤销当前的访问权限),这些都应该反映在缓存中。
我们可以为此目的使用访问和刷新令牌。当使用访问令牌调用API时,资源服务器检查缓存的访问权限。如果有任何新的访问许可,则不会立即反映。一旦访问令牌过期(例如在30分钟内)并且客户端使用刷新令牌生成新的访问令牌,就可以使用来自DB的更新的用户访问权限信息来更新缓存。
换句话说,我们可以将昂贵的操作从使用访问令牌的每次API调用转移到使用刷新令牌生成访问令牌的事件。
这个答案来自Justin Richer通过OAuth 2标准正文电子邮件列表。这是在他的许可下发布的。
刷新令牌的生命周期取决于(AS)授权服务器-它们可以过期、被撤销等。刷新令牌和访问令牌的区别在于受众:刷新令牌只返回授权服务器,访问令牌返回(RS)资源服务器。
此外,仅仅获得访问令牌并不意味着用户已经登录。事实上,用户可能已经不在那里了,这实际上是刷新令牌的预期用例。刷新访问令牌将允许您代表用户访问API,但不会告诉您用户是否在那里。
OpenIDConnect不仅从访问令牌提供用户信息,还提供ID令牌。这是一个单独的数据块,指向客户端本身,而不是AS或RS。在OIDC中,如果您可以获得一个新的ID令牌,您应该只考虑某人实际通过协议“登录”。刷新它可能还不够。
有关更多信息,请阅读http://oauth.net/articles/authentication/