我刚刚开始使用谷歌API和OAuth2。当客户端授权我的应用程序时,我得到一个“刷新令牌”和一个短暂的“访问令牌”。现在每次访问令牌过期,我可以POST我的刷新令牌到谷歌,他们会给我一个新的访问令牌。
我的问题是访问令牌过期的目的是什么?为什么不能有一个持久的访问令牌而不是刷新令牌呢?
另外,刷新令牌是否过期?
有关谷歌OAuth2工作流的更多信息,请参见使用OAuth 2.0访问谷歌api。
我刚刚开始使用谷歌API和OAuth2。当客户端授权我的应用程序时,我得到一个“刷新令牌”和一个短暂的“访问令牌”。现在每次访问令牌过期,我可以POST我的刷新令牌到谷歌,他们会给我一个新的访问令牌。
我的问题是访问令牌过期的目的是什么?为什么不能有一个持久的访问令牌而不是刷新令牌呢?
另外,刷新令牌是否过期?
有关谷歌OAuth2工作流的更多信息,请参见使用OAuth 2.0访问谷歌api。
它本质上是一种安全措施。如果您的应用程序被泄露,攻击者将只能访问短暂的访问令牌,而无法生成一个新的访问令牌。
刷新令牌也会过期,但它们的生存时间应该比访问令牌长得多。
这在很大程度上是特定于实现的,但总体思想是允许提供者使用长期刷新令牌发出短期访问令牌。为什么?
Many providers support bearer tokens which are very weak security-wise. By making them short-lived and requiring refresh, they limit the time an attacker can abuse a stolen token. Large scale deployment don't want to perform a database lookup every API call, so instead they issue self-encoded access token which can be verified by decryption. However, this also means there is no way to revoke these tokens so they are issued for a short time and must be refreshed. The refresh token requires client authentication which makes it stronger. Unlike the above access tokens, it is usually implemented with a database lookup.
有几个场景可能有助于说明访问和刷新令牌的目的,以及在设计oauth2(或任何其他认证)系统时的工程权衡:
Web应用场景
在web应用场景中,你有几个选择:
如果您有自己的会话管理,请在会话状态服务中根据会话状态中的会话id存储access_token和refresh_token。当用户请求一个页面并要求您访问该资源时,使用access_token,如果access_token已经过期,则使用refresh_token获取新页面。
让我们想象一下,有人设法劫持了您的会话。唯一可能的是请求您的页面。
如果您没有会话管理,请将access_token放在cookie中并将其用作会话。然后,每当用户从您的web服务器请求页面时,发送access_token。如果需要,应用服务器可以刷新access_token。
比较1和2:
In 1, access_token and refresh_token only travel over the wire on the way between the authorzation server (google in your case) and your app server. This would be done on a secure channel. A hacker could hijack the session but they would only be able to interact with your web app. In 2, the hacker could take the access_token away and form their own requests to the resources that the user has granted access to. Even if the hacker gets a hold of the access_token they will only have a short window in which they can access the resources.
无论哪种方式,refresh_token和clientid/secret只有服务器知道,因此web浏览器不可能获得长期访问。
让我们想象一下,您正在实现oauth2,并在访问令牌上设置了一个很长的超时:
1)这里短访问令牌和长访问令牌之间没有太大区别,因为它隐藏在应用服务器中。2)有人可以在浏览器中获得access_token,然后使用它来直接访问用户的资源很长一段时间。
移动场景
在手机平台上,我知道有以下几种情况:
将client /secret存储在设备上,并让设备协调获取对用户资源的访问。 使用后端应用服务器保存客户端/秘密,并让它进行编排。使用access_token作为一种会话密钥,并在客户端和应用服务器之间传递它。
比较1和2
In 1) Once you have clientid/secret on the device they aren't secret any more. Anyone can decompile and then start acting as though they are you, with the permission of the user of course. The access_token and refresh_token are also in memory and could be accessed on a compromised device which means someone could act as your app without the user giving their credentials. In this scenario the length of the access_token makes no difference to the hackability since refresh_token is in the same place as access_token. In 2) the clientid/secret nor the refresh token are compromised. Here the length of the access_token expiry determines how long a hacker could access the users resources, should they get hold of it.
到期的长度
在这里,access_token的有效期应该有多长取决于您使用认证系统保护的内容。如果是对用户特别有价值的东西,就应该简短。价值较低的东西,可能会更长。
像谷歌这样的人不会使refresh_token过期。有些人喜欢stackflow。关于过期的决定是用户易用性和安全性之间的权衡。刷新令牌的长度与用户返回的长度相关,也就是说,将刷新设置为用户返回应用程序的频率。如果刷新令牌没有过期,它们被撤销的唯一方式是显式撤销。正常情况下,登录不会失效。
希望比较长的帖子是有用的。
除其他答复外:
一旦获得,访问令牌通常会与客户端的每个请求一起发送到受保护的资源服务器。这导致了访问令牌窃取和重放的风险(当然,假设访问令牌的类型是“holder”(在初始RFC6750中定义)。
这些风险在现实生活中的例子:
Resource Servers generally are distributed application servers and typically have lower security levels compared to Authorization Servers (lower SSL/TLS config, less hardening, etc.). Authorization Servers on the other hand are usually considered as critical Security infrastructure and are subject to more severe hardening. Access Tokens may show up in HTTP traces, logs, etc. that are collected legitimately for diagnostic purposes on the Resource Servers or clients. Those traces can be exchanged over public or semi-public places (bug tracers, service-desk, etc.). Backend RS applications can be outsourced to more or less trustworthy third-parties.
另一方面,刷新令牌通常只在线上传输两次,而且总是在客户端和授权服务器之间传输:一次是客户端获取的,一次是客户端在刷新期间使用的(有效地“过期”前一个刷新令牌)。拦截和回放的机会非常有限。
最后一点,刷新令牌提供的保护很少,如果有的话,针对受损的客户端。
我写了一些这方面的文章,因为我自己今天也在思考这个问题。
https://blog.mukunda.com/cat/2023/refreshing-access-tokens.txt
从本质上讲,我认为只有当刷新令牌在其生命周期内没有保持不变时,才会有主要的安全性提升。
假设有人从您的浏览器cookie中窃取了您的令牌,因为他们暂时访问了您的设备。
如果他们使用了刷新令牌,并且刷新令牌发生了更改,那么您将得到反馈—您将注销。对于谨慎的用户来说,这似乎是合理的怀疑,他们可以采取行动并撤销所有令牌。
如果刷新令牌没有在每次使用时更新,那么就很难注意到有人同时拥有访问权。(很有可能,如果它更新了,那么它可能会在攻击者使用它之前自动从你的设备上更新。)
如果刷新令牌在每次使用时都没有得到更新,那么我看不到该策略在安全性方面的任何提升,因为它将紧挨着访问令牌和客户端机密。
那么,为什么是访问令牌呢?这样你就可以定期检查你的凭证是否有效。
刷新令牌过期了吗?是的,但通常几个月后如果你勾选了"记得我"规范中没有规定失效时间,所以你可以一直执行到失效为止。需要较长时间不受监视会话的服务可能具有秘密凭据,以便它们可以刷新其刷新令牌。
更新:
我还浏览了OAuth 2.0规范,并看到了相同的推理,尽管它强调可以在服务器端捕获无效的身份验证反馈。这是很好的一点——如果令牌被破坏,服务器可以自动撤销令牌。
如果一个刷新令牌被泄露,并且随后被攻击者和合法客户端同时使用,其中一个将提供一个无效的刷新令牌,该刷新令牌将泄露事件通知授权服务器。