OAuth 2.0 协议草案的第 4.2 节指出,授权服务器既可以返回access_token
(用于通过资源对自身进行身份验证),也refresh_token
,后者仅用于创建新的access_token
:
https://tools.ietf.org/html/rfc6749#section-4.2
为什么两者都有?为什么不让access_token
持续到refresh_token
那么长而没有refresh_token
?
由 Catchdave 提供的讨论链接具有Dick Hardt 提出的另一个有效点(原始的,无效的链接),除了上面的内容外,我认为在这里值得一提:
我对刷新令牌的回忆是出于安全性和撤销的考虑。 <...>
撤销:如果访问令牌是自包含的,则可以通过不发布新的访问令牌来撤消授权。资源无需查询授权服务器即可查看访问令牌是否有效。这简化了访问令牌验证,并使扩展和支持多个授权服务器变得更加容易。当访问令牌有效但授权被撤销时,会有一段时间。
确实,在 Resource Server 和 Authorization Server 是同一实体,并且用户与它们中的任何一个之间(通常)同等安全的情况下,将刷新令牌与访问令牌分开是没有多大意义的。
尽管如引用所述,刷新令牌的另一个作用是确保用户可以随时撤消访问令牌(例如,通过其配置文件中的 Web 界面),同时保持系统可扩展性。 。
通常,令牌可以是指向服务器数据库中特定记录的随机标识符,也可以本身包含所有信息(例如,必须使用 MAC对这些信息进行签名)。
具有长期访问令牌的系统应如何工作
服务器允许客户通过发行令牌来在一组预定义的范围内访问用户的数据。因为我们要使令牌可撤消,所以我们必须将令牌以及已设置或未设置的 “revoked” 标志存储在数据库中(否则,如何使用自包含令牌呢?)数据库最多可以包含len(users) x len(registered clients) x len(scopes combination)
记录。然后,每个 API 请求都必须访问数据库。尽管对执行 O(1)的数据库进行查询非常琐碎,但单点故障本身可能会对系统的可伸缩性和性能产生负面影响。
具有长期刷新令牌和短期访问令牌的系统应如何工作
在这里,我们发出两个密钥:具有数据库中相应记录的随机刷新令牌,以及签名的自包含访问令牌,其中包含过期时间戳记字段。
由于访问令牌是独立的,因此我们完全不必点击数据库即可检查其有效性。我们要做的就是解码令牌并验证签名和时间戳。
尽管如此,我们仍然必须保留刷新令牌的数据库,但是对该数据库的请求数通常由访问令牌的寿命来定义(寿命越长,访问速率越低)。
为了撤消特定用户对 Client 的访问,我们应将相应的刷新令牌标记为 “已撤消”(或将其完全删除),并停止发行新的访问令牌。很明显,尽管有一个窗口在其中刷新令牌已被吊销,但是其访问令牌可能仍然有效。
权衡
刷新令牌部分地消除了访问令牌数据库的 SPoF(单点故障),但是它们有一些明显的缺点。
窗户”。事件 “用户撤消访问权限” 和 “保证撤消访问权限” 之间的时间范围。
客户逻辑的复杂性。
没有刷新令牌
带有刷新令牌
我希望这个答案确实有意义,并且可以帮助别人做出更周到的决定。我还要指出,一些著名的 OAuth2 提供程序(包括 github 和 foursquare)采用了不带刷新令牌的协议,因此对此感到满意。
刷新令牌的想法是,如果访问令牌由于生存期短而受到威胁,则攻击者将有一个滥用它的窗口。
刷新令牌(如果遭到破坏)是无用的,因为攻击者除了需要刷新令牌之外还需要客户端 ID 和机密才能获得访问令牌。
话虽如此,因为对授权服务器和资源服务器的每次调用都是通过 SSL 进行的 - 包括原始客户端 ID 和请求访问 / 刷新令牌时的机密 - 我不确定访问令牌又如何了” 易损”,而不是长期的刷新令牌和 clientid / secret 组合。
当然,这与不同时控制授权服务器和资源服务器的实现有所不同。
这是一个讨论刷新令牌使用的好线程: OAuth Archives 。
上面的引言,谈到了刷新令牌的安全性目的:
刷新令牌... 减轻了 access_token 长期泄漏的风险(在不安全的资源服务器,beta 或编码不正确的资源服务器应用,非 https 站点上的 JS SDK 客户端上的日志文件中的查询参数,将 access_token 放在 Cookie 等)
尽管有上述所有出色的答案,但作为安全硕士和程序员,我以前曾在 eBay 工作过,当时我研究了买家保护和欺诈行为,可以说分离访问令牌和刷新令牌在骚扰频繁使用用户名的用户之间具有最佳平衡/ password 输入,并保留授权以撤消对您的服务的潜在滥用的访问权限。
想想这样的情况。您向用户颁发了 3600 秒的访问令牌,并且刷新令牌的时间长达一天。
该用户是一个好用户,他在家中,就可以在您的 iPhone 上开 / 关您的网站购物和搜索。他的 IP 地址不会改变,并且服务器负载很低。每分钟有 3-5 页的请求。当他在访问令牌上的 3600 秒结束时,他需要一个带有刷新令牌的新令牌。在服务器端,我们检查了他的活动历史记录和 IP 地址,认为他是一个人并且表现得很好。我们授予他一个新的访问令牌,以继续使用我们的服务。用户在达到刷新令牌本身的一天寿命之前,无需再次输入用户名 / 密码。
该用户是粗心的用户。他住在美国纽约,并关闭了病毒程序,并被波兰的一名黑客入侵。当黑客获得访问令牌和刷新令牌时,他会尝试模拟用户并使用我们的服务。但是在短期访问令牌过期后,当黑客尝试刷新访问令牌时,我们在服务器上注意到用户行为历史记录中的 IP 发生了巨大变化(嘿,这个人登录了美国,现在在波兰刷新了访问权限只需 3600 秒???)。我们终止刷新过程,使刷新令牌本身无效,并提示再次输入用户名 / 密码。
该用户是恶意用户。他打算通过使用机器人每分钟调用 1000 次我们的 API 来滥用我们的服务。他可以这样做直到 3600 秒后,当他尝试刷新访问令牌时,我们注意到他的行为,并认为他可能不是人类。我们拒绝并终止刷新过程,并要求他再次输入用户名 / 密码。这可能会破坏他的机器人的自动流程。至少使他不舒服。
当我们尝试平衡工作,用户体验和令牌被盗的潜在风险时,您可以看到刷新令牌运行得很好。您在服务器端的看门狗不仅可以检查 IP 更改,api 调用的频率,还可以确定该用户是否为好用户。
换句话说,您还可以尝试通过在每个 api 调用上实现基本 IP 看门狗或任何其他措施来限制对被盗令牌 / 服务滥用的破坏控制。但这很昂贵,因为您必须读写有关用户的记录,并且会减慢服务器的响应速度。