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?
当前回答
为了进一步简化B T的答案:当您通常不希望用户再次输入凭据,但仍然希望能够撤销权限(通过撤销刷新令牌)时,请使用刷新令牌
您不能撤销访问令牌,只能撤销刷新令牌。
其他回答
尽管上面的答案很好,但我作为一名安全硕士生和程序员,在研究买家保护和欺诈时,曾在eBay工作过,可以说,将访问令牌和刷新令牌分开,在骚扰频繁输入用户名/密码的用户和保留撤销对可能滥用您服务的访问权限之间取得了最佳平衡。
想象一下这样的情景。您向用户发出3600秒的访问令牌,刷新令牌的时间长达一天。
用户是一个好用户,他在家里,上下你的网站,在他的iPhone上购物和搜索。他的IP地址不会改变,并且服务器负载很低。像每分钟3-5页的请求。当他在访问令牌上的3600秒结束时,他需要一个具有刷新令牌的新令牌。在服务器端,我们检查他的活动历史和IP地址,认为他是一个人,行为举止得体。我们授予他一个新的访问令牌以继续使用我们的服务。用户不需要再次输入用户名/密码,直到达到刷新令牌本身的一天寿命。用户是一个粗心大意的用户。他住在美国纽约,病毒程序被关闭,在波兰被黑客入侵。当黑客获得访问令牌和刷新令牌时,他试图模拟用户并使用我们的服务。但是,在短暂的实时访问令牌过期后,当黑客试图刷新访问令牌时,我们在服务器上注意到用户行为历史中的IP发生了巨大变化(嘿,这家伙在美国登录,现在在波兰仅3600秒后刷新访问)。我们终止刷新过程,使刷新令牌本身无效,并提示再次输入用户名/密码。该用户是恶意用户。他打算通过使用机器人每分钟调用1000次我们的API来滥用我们的服务。直到3600秒后,当他试图刷新访问令牌时,我们注意到他的行为,认为他可能不是人类。我们拒绝并终止刷新过程,并要求他再次输入用户名/密码。这可能会破坏他的机器人的自动流动。至少让他不舒服。
当我们试图平衡我们的工作、用户体验和被盗令牌的潜在风险时,您可以看到刷新令牌的表现非常完美。服务器端的看门狗不仅可以检查IP更改,还可以检查api调用的频率,以确定用户是否应该是一个好用户。
另一个词是,您还可以尝试通过在每个api调用上实现基本IP看门狗或任何其他措施来限制被盗令牌/滥用服务的损害控制。但这很昂贵,因为您必须读取和写入有关用户的记录,并且会降低服务器响应速度。
为什么不让access_token和refresh_token一样长不吃点心吗?
除了其他人提供的出色答案之外,我们使用刷新令牌还有另一个原因,这与声明有关。
每个令牌都包含声明,这些声明可以包括用户名、用户角色或创建声明的提供者等任何内容。当刷新令牌时,这些声明将被更新。
如果我们更频繁地刷新令牌,显然会给我们的身份服务带来更大的压力;然而,我们正在获得更准确和最新的声明。
据我所知,如果您需要撤销访问,刷新令牌只是为了性能和成本节省。
例1:不实现刷新令牌;仅实现长期访问令牌:如果用户滥用服务(例如:不支付订阅),您需要能够撤销访问令牌=>您需要在每个需要访问令牌的API调用上检查访问令牌的有效性,这会很慢,因为它需要DB查找(缓存可以帮助,但这更复杂)。
例2:实现刷新令牌和短期访问令牌:如果用户滥用服务(例如:不支付订阅),您需要能够撤销访问令牌=>短暂的访问令牌将在短暂的白色(例如1小时)后过期,用户将需要获得新的访问令牌,因此我们不需要对需要访问令牌的每个API调用进行验证。您只需要在从刷新令牌生成访问令牌时验证用户。对于坏用户,如果无法生成访问令牌,则可以注销该用户。当用户尝试重新登录时,验证将再次运行并返回错误。
为了理解这个问题的答案,我们需要了解两点。
第一点是,有时用户的访问令牌可能会在用户不知情的情况下被盗。由于用户不知道攻击,他们将无法手动通知我们。然后,就我们给攻击者完成攻击的时间(机会)而言,15分钟和一整天之间会有巨大的差异。因此,这就是我们需要每“短时间”(例如,每15分钟)“刷新”访问令牌的原因,我们不想将此操作推迟很长时间(例如,一整天)。因此,OP在问题中所说的显然不是一个选项(将访问令牌的到期时间延长到刷新令牌的有效时间)。
因此,我们至少还有以下两个选择:
要求每个用户每隔一段时间重新输入他们的凭据,以便为他们提供新的访问令牌。但显然,这不是一个流行的选项,因为它会困扰用户。使用刷新令牌。阅读下面的第二点,以了解其工作原理(背后的逻辑)。
第二点需要理解的是,因为我们已经将访问令牌与刷新令牌分开,现在可以以“不同的方式”发送刷新令牌,因此我们可以以攻击者的JavaScript(通常是客户端代码)无法访问的方式发送它,例如,使用httpOnly标记:
HttpOnly Cookie是添加到浏览器Cookie中的标记,用于阻止客户端脚本访问数据。来源
在生成cookie时使用HttpOnly标志有助于降低客户端脚本访问受保护cookie的风险。HttpOnly cookie于2002年由Microsoft Internet Explorer开发人员针对Internet Explorer 6 SP1首次实现。来源(感谢IE!)
因此,尽管攻击者仍然可以窃取访问令牌(强烈建议将其保存在RAM中,而不是本地存储等易受攻击的地方),但他们将无法窃取刷新令牌。因此,如果攻击者窃取了一个人的访问令牌,他们只有很短的时间滥用它(15分钟?比一整天好得多!),然后一旦它过期,他们就没有机会自己获得新的令牌。
让我们考虑一个系统,其中每个用户链接到一个或多个角色,每个角色链接到一种或多种访问权限。可以缓存这些信息以获得更好的API性能。但是,用户和角色配置可能会发生变化(例如,可能会授予新的访问权限,或者可能会撤销当前的访问权限),这些都应该反映在缓存中。
我们可以为此目的使用访问和刷新令牌。当使用访问令牌调用API时,资源服务器检查缓存的访问权限。如果有任何新的访问许可,则不会立即反映。一旦访问令牌过期(例如在30分钟内)并且客户端使用刷新令牌生成新的访问令牌,就可以使用来自DB的更新的用户访问权限信息来更新缓存。
换句话说,我们可以将昂贵的操作从使用访问令牌的每次API调用转移到使用刷新令牌生成访问令牌的事件。