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?
当前回答
尽管上面的答案很好,但我作为一名安全硕士生和程序员,在研究买家保护和欺诈时,曾在eBay工作过,可以说,将访问令牌和刷新令牌分开,在骚扰频繁输入用户名/密码的用户和保留撤销对可能滥用您服务的访问权限之间取得了最佳平衡。
想象一下这样的情景。您向用户发出3600秒的访问令牌,刷新令牌的时间长达一天。
用户是一个好用户,他在家里,上下你的网站,在他的iPhone上购物和搜索。他的IP地址不会改变,并且服务器负载很低。像每分钟3-5页的请求。当他在访问令牌上的3600秒结束时,他需要一个具有刷新令牌的新令牌。在服务器端,我们检查他的活动历史和IP地址,认为他是一个人,行为举止得体。我们授予他一个新的访问令牌以继续使用我们的服务。用户不需要再次输入用户名/密码,直到达到刷新令牌本身的一天寿命。用户是一个粗心大意的用户。他住在美国纽约,病毒程序被关闭,在波兰被黑客入侵。当黑客获得访问令牌和刷新令牌时,他试图模拟用户并使用我们的服务。但是,在短暂的实时访问令牌过期后,当黑客试图刷新访问令牌时,我们在服务器上注意到用户行为历史中的IP发生了巨大变化(嘿,这家伙在美国登录,现在在波兰仅3600秒后刷新访问)。我们终止刷新过程,使刷新令牌本身无效,并提示再次输入用户名/密码。该用户是恶意用户。他打算通过使用机器人每分钟调用1000次我们的API来滥用我们的服务。直到3600秒后,当他试图刷新访问令牌时,我们注意到他的行为,认为他可能不是人类。我们拒绝并终止刷新过程,并要求他再次输入用户名/密码。这可能会破坏他的机器人的自动流动。至少让他不舒服。
当我们试图平衡我们的工作、用户体验和被盗令牌的潜在风险时,您可以看到刷新令牌的表现非常完美。服务器端的看门狗不仅可以检查IP更改,还可以检查api调用的频率,以确定用户是否应该是一个好用户。
另一个词是,您还可以尝试通过在每个api调用上实现基本IP看门狗或任何其他措施来限制被盗令牌/滥用服务的损害控制。但这很昂贵,因为您必须读取和写入有关用户的记录,并且会降低服务器响应速度。
其他回答
尽管上面的答案很好,但我作为一名安全硕士生和程序员,在研究买家保护和欺诈时,曾在eBay工作过,可以说,将访问令牌和刷新令牌分开,在骚扰频繁输入用户名/密码的用户和保留撤销对可能滥用您服务的访问权限之间取得了最佳平衡。
想象一下这样的情景。您向用户发出3600秒的访问令牌,刷新令牌的时间长达一天。
用户是一个好用户,他在家里,上下你的网站,在他的iPhone上购物和搜索。他的IP地址不会改变,并且服务器负载很低。像每分钟3-5页的请求。当他在访问令牌上的3600秒结束时,他需要一个具有刷新令牌的新令牌。在服务器端,我们检查他的活动历史和IP地址,认为他是一个人,行为举止得体。我们授予他一个新的访问令牌以继续使用我们的服务。用户不需要再次输入用户名/密码,直到达到刷新令牌本身的一天寿命。用户是一个粗心大意的用户。他住在美国纽约,病毒程序被关闭,在波兰被黑客入侵。当黑客获得访问令牌和刷新令牌时,他试图模拟用户并使用我们的服务。但是,在短暂的实时访问令牌过期后,当黑客试图刷新访问令牌时,我们在服务器上注意到用户行为历史中的IP发生了巨大变化(嘿,这家伙在美国登录,现在在波兰仅3600秒后刷新访问)。我们终止刷新过程,使刷新令牌本身无效,并提示再次输入用户名/密码。该用户是恶意用户。他打算通过使用机器人每分钟调用1000次我们的API来滥用我们的服务。直到3600秒后,当他试图刷新访问令牌时,我们注意到他的行为,认为他可能不是人类。我们拒绝并终止刷新过程,并要求他再次输入用户名/密码。这可能会破坏他的机器人的自动流动。至少让他不舒服。
当我们试图平衡我们的工作、用户体验和被盗令牌的潜在风险时,您可以看到刷新令牌的表现非常完美。服务器端的看门狗不仅可以检查IP更改,还可以检查api调用的频率,以确定用户是否应该是一个好用户。
另一个词是,您还可以尝试通过在每个api调用上实现基本IP看门狗或任何其他措施来限制被盗令牌/滥用服务的损害控制。但这很昂贵,因为您必须读取和写入有关用户的记录,并且会降低服务器响应速度。
这个答案是在两位高级开发人员(约翰·布莱顿和大卫·詹内斯)的帮助下得出的。
使用刷新令牌的主要原因是减少攻击面。
假设没有刷新键,让我们来看看这个示例:
一座大楼有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调用进行验证。您只需要在从刷新令牌生成访问令牌时验证用户。对于坏用户,如果无法生成访问令牌,则可以注销该用户。当用户尝试重新登录时,验证将再次运行并返回错误。
让我们考虑一个系统,其中每个用户链接到一个或多个角色,每个角色链接到一种或多种访问权限。可以缓存这些信息以获得更好的API性能。但是,用户和角色配置可能会发生变化(例如,可能会授予新的访问权限,或者可能会撤销当前的访问权限),这些都应该反映在缓存中。
我们可以为此目的使用访问和刷新令牌。当使用访问令牌调用API时,资源服务器检查缓存的访问权限。如果有任何新的访问许可,则不会立即反映。一旦访问令牌过期(例如在30分钟内)并且客户端使用刷新令牌生成新的访问令牌,就可以使用来自DB的更新的用户访问权限信息来更新缓存。
换句话说,我们可以将昂贵的操作从使用访问令牌的每次API调用转移到使用刷新令牌生成访问令牌的事件。
刷新令牌和访问令牌只是术语。
这个小小的类比可以帮助巩固使用访问令牌和刷新令牌背后的理论基础:
假设Alice通过邮寄给Bob一张支票,该支票可以在出票后1小时内兑现(假设),否则银行不会兑现。但Alice还在给银行的邮件中附上了一张纸条,要求银行接受并兑现支票,以防支票延迟(在规定范围内)
当Bob收到这张支票时,如果他看到这张支票被篡改(令牌篡改),他将自己丢弃这张支票。如果没有,他可以把它拿到银行兑现。在这里,当银行注意到发行时间超过了1小时的时限,但看到Alice的签名通知,要求银行在规定的延迟范围内兑现。
看到这张纸条后,银行会尝试验证签名的消息,并检查Alice是否仍然具有正确的权限。如果是,银行将支票兑现。鲍勃现在可以向爱丽丝承认这一点了。
虽然不是非常准确,但这个类比可以帮助您注意到处理事务所涉及的不同部分:
Alice(发件人-客户)Bob(接收者-资源服务器)银行(授权服务器)验证过程(数据库访问)支票(访问令牌)备注(刷新令牌)
主要是,为了优化可伸缩性,我们希望减少对Auth Server以及最终对数据库的API调用次数。我们需要在方便和安全之间取得适当的平衡。
注意:与链中的资源服务器相比,让Auth服务器更早地响应请求当然更常见。