我不得不承认我有这个问题很长时间了,从来没有真正理解过。
说身份验证令牌就像保险箱的钥匙,当它过期时就不再可用了。现在我们得到了一个魔法刷新令牌,它可以用来获取另一个可用的密钥,以及另一个……直到魔法密钥过期。那么为什么不将身份验证令牌的到期时间设置为与刷新令牌相同呢?为什么要打扰呢?
它的正当理由是什么,也许是历史原因?真的很想知道。谢谢
我不得不承认我有这个问题很长时间了,从来没有真正理解过。
说身份验证令牌就像保险箱的钥匙,当它过期时就不再可用了。现在我们得到了一个魔法刷新令牌,它可以用来获取另一个可用的密钥,以及另一个……直到魔法密钥过期。那么为什么不将身份验证令牌的到期时间设置为与刷新令牌相同呢?为什么要打扰呢?
它的正当理由是什么,也许是历史原因?真的很想知道。谢谢
前几天我正在阅读Taiseer Joudeh的一篇文章,我觉得它非常有用,他说:
在我自己看来,使用刷新令牌有三个主要好处:
更新访问令牌内容:如您所知,访问令牌是自包含的令牌,一旦生成,它们就会包含有关经过身份验证的用户的所有声明(信息),现在如果我们为用户颁发长期令牌(例如 1 个月)命名为“Alex”并将他注册为“用户”角色,然后此信息将包含在授权服务器生成的令牌中。如果您稍后决定(在他获得令牌后 2 天)将他添加到“管理员”角色,则无法更新生成的令牌中包含的此信息,您需要让他重新自我验证所以授权服务器将此信息添加到这个新生成的访问令牌中,这在大多数情况下是不可行的。您可能无法联系获得长期访问令牌的用户。
撤销经过身份验证的用户的访问:一旦用户获得长期访问令牌,只要他的访问令牌未过期,他就能够访问服务器资源,除非授权服务器实现自定义逻辑,否则没有标准的方法来撤销访问令牌这迫使您将生成的访问令牌存储在数据库中,并对每个请求进行数据库检查。但是使用刷新令牌,系统管理员可以通过简单地从数据库中删除刷新令牌标识符来撤销访问,因此一旦系统使用已删除的刷新令牌请求新的访问令牌,授权服务器将拒绝此请求,因为刷新令牌不再可用(我们将详细介绍这一点)。
无需存储或询问用户名和密码:使用刷新令牌允许您在用户第一次身份验证后仅向用户询问他的用户名和密码一次,然后授权服务器可以发出非常长的刷新令牌(1 年例如),除非系统管理员尝试撤销刷新令牌,否则用户将一直保持登录状态。您可以将其视为对服务器资源进行离线访问的一种方式,如果您正在构建一个将由前端应用程序使用的 API,而在这种情况下不断询问用户名/密码是不可行的,这可能会很有用。
我想补充另一个观点。
假设您想创建一个无状态(无会话)安全机制,可以对数百万用户进行身份验证,而无需进行数据库调用来进行身份验证。对于您的应用程序获得的所有流量,为每个请求节省一次数据库调用非常值得!而且它需要是无状态的,以便可以轻松地集群并扩展到数百甚至数千台服务器。
使用老式会话,用户登录,此时我们从数据库中读取他们的用户信息。为了避免一次又一次地读取它,我们将它存储在会话中(通常在内存或一些集群缓存中)。我们将会话 ID 在 cookie 中发送给客户端,该 cookie 附加到所有后续请求。在后续请求中,我们使用会话 ID 来查找会话,该会话又包含用户信息。
但我们不想要会话。因此,我们不将用户信息存储在会话中,而是将其放入访问令牌中。我们对令牌进行签名,因此没有人可以篡改它并立即生效。我们可以在没有会话的情况下对请求进行身份验证,并且不必从数据库中为每个请求查找用户信息。
但是没有会议有一个很大的缺点。例如,如果该用户被禁止怎么办?在旧场景中,我们只是删除他的会话。然后他必须再次登录,而他将无法做到这一点。禁令完成。但是在新场景中没有会话。那我们怎么禁止他呢?我们将不得不(非常有礼貌地)要求他删除他的访问令牌。根据禁止列表检查每个传入请求?是的,会起作用,但现在我们必须再次进行我们不想要的数据库调用。
如果我们认为用户可能在被禁止 10 分钟后仍然可以使用他的帐户是可以接受的,我们可以创建一种在每次请求检查数据库和仅在登录时检查数据库之间的折衷方案。这就是刷新令牌的用武之地。它们允许我们使用具有短期访问令牌的无状态机制。我们无法撤销这些令牌,因为没有对它们进行数据库检查。我们只根据当前时间检查它们的到期日期。但是一旦它们过期,用户将需要提供刷新令牌来获取新的访问令牌。在这一点上,我们确实检查了 DB 并看到该用户已被禁止。所以我们拒绝访问令牌的请求,禁令生效。
引用的答案(通过@Anders)很有帮助,它指出:
万一被泄露,它的有效时间窗口是有限的,但令牌是通过 SSL 使用的,因此不太可能被泄露。
我认为重要的部分是访问令牌通常会被记录(特别是当用作查询参数时,这对 JSONP 很有帮助),因此最好将它们设为短暂的。
还有一些其他原因,服务提供商大规模实施 OAuth 2.0:
如果不必担心撤销,API 服务器可以安全地验证访问令牌而无需数据库查找或 RPC 调用。这可以带来强大的性能优势并降低 API 服务器的复杂性。如果您可以接受 30m-60m(或任何访问令牌的长度)的令牌撤销,则最好。当然,API 服务器也可以在内存中保留最近一小时内撤销的令牌列表。
由于令牌可以具有多个范围,可以访问多个不同的 API 服务,因此拥有短期访问令牌会阻止 API 服务的开发人员终身访问 API 服务 B 上的用户数据。划分有利于安全性。
缩短可能的答案:
刷新令牌允许令牌的范围/不同衰减时间。实际资源令牌是短暂的,而刷新令牌可以保持多年有效(移动应用程序)。这带来了更好的安全性(资源令牌不必受到保护)和性能(只有刷新令牌 API 必须检查数据库的有效性)。
以下是已经提到的刷新令牌的好处的补充。
访问令牌是短暂的。如果有人窃取了访问令牌,他只能在访问令牌过期之前访问资源。
如果攻击者窃取了刷新令牌,他可以获得访问令牌。出于这个原因,它建议每次获得新的访问令牌时都发布一个新的刷新令牌。如果相同的刷新令牌被使用了两次,则很可能意味着刷新令牌被盗了。
当每次使用后刷新令牌发生变化时,如果授权服务器曾经检测到刷新令牌被使用了两次,则意味着它可能已被复制并正在被攻击者使用,并且授权服务器可以撤销所有访问令牌和刷新令牌相关联立即使用它。
https://www.oauth.com/oauth2-servers/making-authenticated-requests/refreshing-an-access-token/
当然,这只是另一层安全性。攻击者仍有时间获取访问令牌,直到第二次使用刷新令牌(攻击者或真实用户)。
请始终牢记,刷新令牌必须尽可能安全地存储。