为什么OAuth v2同时具有访问权限和刷新令牌?

时间:2010-08-15 15:25:41

标签: security oauth access-token refresh-token

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

15 个答案:

答案 0 :(得分:506)

由Catchdave提供的讨论链接还有另一个由Dick Hardt制作的valid point (original, dead link),我认为除了上面所写的内容之外,我还相信值得提及:

  

我对刷新令牌的回忆是为了安全和撤销。   < ...>

     

吊销:如果访问令牌是自包含的,则可以通过不发布新的访问令牌来撤销授权。资源不需要查询授权服务器以查看访问令牌是否有效。这简化了访问令牌验证,并使得更容易扩展和支持多个授权服务器。访问令牌有效时有一个时间窗口,但授权被撤销。

实际上,在资源服务器和授权服务器是同一个实体的情况下,以及用户与其中任何一个之间的连接(通常)同样安全的情况下,将刷新令牌与访问令牌分开是没有多大意义的

虽然如引言中所述,刷新令牌的另一个作用是确保用户可以随时撤销访问令牌(例如,通过其配置文件中的Web界面),同时保持系统的可扩展性同时。

通常,令牌可以是指向服务器数据库中特定记录的随机标识符,也可以包含所有信息(当然,必须使用MAC对此信息进行签名)。

具有长期访问令牌的系统应如何运作

服务器允许客户端通过发出令牌来访问预定义范围集内的用户数据。由于我们希望保持令牌可撤销,我们必须在数据库中存储令牌以及设置或取消设置的“已撤销”标志(否则,您将如何使用自包含令牌执行此操作?)数据库可以包含尽可能多的{ {1}}记录。然后,每个API请求都必须访问数据库。虽然对这样的数据库执行O(1)查询非常简单,但单点故障本身可能会对系统的可伸缩性和性能产生负面影响。

具有长期刷新令牌和短期访问令牌的系统应如何工作

这里我们发出两个密钥:随机刷新令牌和数据库中的相应记录,以及签名的自包含访问令牌,其中包含到期时间戳字段。

由于访问令牌是自包含的,我们根本不需要访问数据库来检查其有效性。我们所要做的就是解码令牌并验证签名和时间戳。

尽管如此,我们仍然需要保留刷新令牌的数据库,但是对此数据库的请求数通常由访问令牌的生命周期定义(生命周期越长,访问率越低)。

为了撤销客户对特定用户的访问,我们应将相应的刷新令牌标记为“已撤销”(或完全删除)并停止发出新的访问令牌。很明显,虽然有一个窗口,在此期间刷新令牌已被撤销,但其访问令牌可能仍然有效。

<强>权衡

刷新令牌部分消除了访问令牌数据库的SPoF(单点故障),但它们有一些明显的缺点。

  1. “窗口”。事件“用户撤销访问权限”和“访问权限保证被撤销”之间的时间范围。

  2. 客户逻辑的复杂性。

    没有刷新令牌

    • 发送带有访问令牌的API请求
    • 如果访问令牌无效,则失败并要求用户重新进行身份验证

    刷新令牌

    • 发送带有访问令牌的API请求
    • 如果访问令牌无效,请尝试使用刷新令牌
    • 更新它
    • 如果刷新请求通过,则更新访问令牌并重新发送初始API请求
    • 如果刷新请求失败,请要求用户重新进行身份验证
  3. 我希望这个答案确实有意义并帮助某人做出更周到的决定。我还要注意一些着名的OAuth2提供商,包括github和foursquare,采用没有刷新令牌的协议,并且看起来很满意。

答案 1 :(得分:407)

刷新令牌的想法是,如果访问令牌被泄露,因为它是短暂的,攻击者有一个有限的窗口可以滥用它。

刷新令牌(如果受到攻击)是无用的,因为除了刷新令牌之外,攻击者还需要客户端ID和机密才能获得访问令牌。

说了,因为对授权服务器和资源服务器的每次调用都是通过SSL完成的 - 包括原始客户端ID和秘密请求访问/刷新令牌时 - 我不确定关于访问令牌如何比长期刷新令牌和clientid / secret组合更“可妥协”。

这当然与您不同时控制授权和资源服务器的实现不同。

这是一个讨论刷新令牌使用的好主题:OAuth Archives

以上引用,讨论刷新令牌的安全目的:

  

刷新令牌......降低了长期存在的access_token泄漏的风险(在不安全的资源服务器,测试版或编码不良的资源服务器应用程序上的日志文件中查询参数,非https网站上的JS SDK客户端cookie中的access_token等)

答案 2 :(得分:152)

Despite all the great answers above, I as a security master student and programmer who previously worked at eBay when I took a look into buyer protection and fraud, can say to separate access token and refresh token has its best balance between harassing user of frequent username/password input and keeping the authority in hand to revoke access to potential abuse of your service.

Think of a scenario like this. You issue user of an access token of 3600 seconds and refresh token much longer as one day.

  1. The user is a good user, he is at home and gets on/off your website shopping and searching on his iPhone. His IP address doesn't change and have a very low load on your server. Like 3-5 page requests every minute. When his 3600 seconds on the access token is over, he requires a new one with the refresh token. We, on the server side, check his activity history and IP address, think he is a human and behaves himself. We grant him a new access token to continue using our service. The user won't need to enter again the username/password until he has reached one day life-span of refresh token itself.

  2. The user is a careless user. He lives in New York, USA and got his virus program shutdown and was hacked by a hacker in Poland. When the hacker got the access token and refresh token, he tries to impersonate the user and use our service. But after the short-live access token expires, when the hacker tries to refresh the access token, we, on the server, has noticed a dramatic IP change in user behavior history (hey, this guy logins in USA and now refresh access in Poland after just 3600s ???). We terminate the refresh process, invalidate the refresh token itself and prompt to enter username/password again.

  3. The user is a malicious user. He is intended to abuse our service by calling 1000 times our API each minute using a robot. He can well doing so until 3600 seconds later, when he tries to refresh the access token, we noticed his behavior and think he might not be a human. We reject and terminate the refresh process and ask him to enter username/password again. This might potentially break his robot's automatic flow. At least makes him uncomfortable.

You can see the refresh token has acted perfectly when we try to balance our work, user experience and potential risk of a stolen token. Your watch dog on the server side can check more than IP change, frequency of api calls to determine whether the user shall be a good user or not.

Another word is you can also try to limit the damage control of stolen token/abuse of service by implementing on each api call the basic IP watch dog or any other measures. But this is expensive as you have to read and write record about the user and will slow down your server response.

答案 3 :(得分:65)

这些答案都没有达到刷新令牌存在的核心原因。显然,您可以通过将您的客户端凭据发送到auth服务器来获得新的访问令牌/刷新令牌对 - 这就是您首先获得它们的方式。

因此刷新令牌的唯一目的是限制通过线路发送到auth服务的客户端凭证的使用。访问令牌的ttl越短,客户端凭证就越需要用于获取新的访问令牌,因此攻击者必须破坏客户端凭证的机会越多(尽管如果这可能是非常困难的,如果非对称加密用于发送它们)。因此,如果您有一次性使用刷新令牌,则可以在不影响客户端凭据的情况下使访问令牌的ttl任意小。

答案 4 :(得分:43)

要澄清一些困惑,您必须了解 client secret 用户密码的角色,这些角色非常不同。

客户端是一个app / website / program / ...,由服务器支持,希望用户进行身份验证使用第三方身份验证服务。客户端密钥是此客户端和身份验证服务器都知道的(随机)字符串。使用此秘密,客户端可以使用身份验证服务器识别自己,接收授权以请求访问令牌。

要获取初始访问令牌和刷新令牌,需要的是:

  • 用户ID
  • 用户密码
  • 客户端ID
  • 客户端秘密

要获取刷新的访问令牌,客户端使用以下信息:

  • 客户端ID
  • 客户端秘密
  • 刷新令牌

这清楚地表明了区别:刷新时,客户端通过使用其客户端密钥获得刷新访问令牌的授权,因此可以使用用户ID的刷新令牌而不是重新验证用户身份+密码。这有效地防止了用户重新输入他/她的密码。

这也表明丢失刷新令牌没有问题,因为客户端ID和机密信息是未知的。它还表明,保持客户端ID和客户端机密是至关重要的

答案 5 :(得分:35)

这个答案来自Justin Richer通过OAuth 2标准正文电子邮件列表。这是在他允许的情况下发布的。

刷新令牌的生命周期取决于(AS)授权服务器 - 它们可以过期,被撤销等。刷新令牌和访问令牌之间的区别在于受众:刷新令牌只返回到授权服务器,访问令牌转到(RS)资源服务器。

此外,仅获取访问令牌并不意味着用户已登录。实际上,用户可能甚至不再在那里,这实际上是刷新令牌的预期用例。刷新访问令牌将允许您代表用户访问API,它不会告诉您用户是否在那里。

OpenID Connect不仅为您提供来自访问令牌的用户信息,还为您提供ID令牌。这是一个单独的数据,针对客户端本身,而不是AS或RS。在OIDC中,如果您可以获得新的ID令牌,则应该只考虑通过协议实际“登录”的人。刷新它可能不够。

有关详细信息,请参阅http://oauth.net/articles/authentication/

答案 6 :(得分:18)

客户可能会在很多方面受到损害。例如,可以克隆手机。访问令牌过期意味着客户端被迫重新向授权服务器进行身份验证。在重新认证期间,授权服务器可以检查其他特征(IOW执行自适应访问管理)。

刷新令牌只允许客户端重新进行身份验证,而重新授权会强制与用户进行对话,许多人都表示他们不愿意这样做。

刷新令牌基本上适合普通网站可能选择在一小时左右后定期重新验证用户的相同位置(例如银行网站)。目前它没有被高度使用,因为大多数社交网站都没有重新验证网络用户,那么他们为什么会重新验证客户端呢?

答案 7 :(得分:12)

进一步简化B T的答案:当您通常不希望用户必须再次输入凭据时,请使用刷新令牌,但仍希望权力能够撤销权限(通过撤销刷新令牌)

您无法撤消访问令牌,只能撤消刷新令牌。

答案 8 :(得分:9)

  

为什么不将access_token设置为与refresh_token一样长   并且没有refresh_token?

除了其他人提供的很好的答案之外,还有另一个原因可以使用刷新令牌及其与声明有关。

每个令牌都包含声明,其中可以包含用户名称,角色或创建声明的提供程序中的任何内容。随着令牌的刷新,这些声明会更新。

如果我们更频繁地更新代币,我们显然会对我们的身份服务施加更大压力,但我们会获得更准确和最新的声明。

答案 9 :(得分:5)

这个答案是在两位资深开发人员(约翰·布雷顿和大卫·詹尼斯)的帮助下综合起来的。

使用刷新令牌的主要原因是为了减少攻击面。

我们假设没有刷新键,让我们看一下这个示例:

一幢建筑物有80门。所有门都用同一把钥匙打开。密钥每30分钟更改一次。

如果我是黑客并获取了您的密钥,那么在30分钟结束时,我会将该信息快递给密钥制作者并获取新密钥。无论按键如何更改,我都可以连续打开所有门。

问题:在30分钟内,我有多少次针对密钥的黑客入侵活动?每次您使用密钥时,我都有80次黑客机会(可以将其视为发出网络请求并传递访问令牌以识别自己的身份)。这就是80倍的攻击面。

现在让我们来看一个例子,但是这次我们假设有一个刷新键。

一幢建筑物有80门。所有门都用同一把钥匙打开。密钥每30分钟更改一次。 如果我是黑客并获得了您的密钥,则可以使用它30分钟,但在30分钟结束时将其发送给密钥制作者没有任何价值。如果我这样做,那么密钥制作者只会说此密钥已过期。为了能够扩展我的破解能力,我必须将快递员破解给密钥制作者。快递员有一个独特的钥匙(可以将其视为刷新令牌)。

问题:在30分钟内,我有多少次针对快递员的骇客机会? 80?不。我只有1次骇客机会。在此期间,快递员与制琴师进行沟通。这就是1倍的攻击面。 我确实有80次针对密钥的骇客机会,但30分钟后就没用了。


服务器将基于凭据和(通常)JWT的签名来验证访问令牌。

访问令牌泄漏很严重,但是一旦过期,它就不再对攻击者有用。刷新令牌泄漏的情况要严重得多,但是大概不太可能。 (我认为仍有疑问,刷新令牌泄漏的可能性是否比访问令牌泄漏的可能性低得多,但这就是这个主意。)

重点是访问令牌会添加到您提出的每个请求中,而刷新令牌仅在刷新流程中使用 这样一来,MITM看到令牌的机会就更少了

频率可以帮助攻击者。像Heartbleed这样的SSL中潜在的安全漏洞,客户端中的潜在安全漏洞以及服务器中的潜在安全漏洞都使泄漏成为可能。

此外,如果授权服务器与处理其他客户端请求的应用程序服务器分离,则该应用程序服务器将永远不会看到刷新令牌。它只会看到访问令牌,该令牌将不会存在更长时间。

区隔有利于安全。


什么不是刷新令牌?

通过刷新令牌更新/撤消访问级别的能力是选择使用刷新令牌的副产品,否则,独立的访问令牌可能会被吊销或在其过期且用户获得新令牌时对其访问级别进行修改”。

答案 10 :(得分:4)

假设您使access_token持续很长时间,并且没有refresh_token,那么黑客有一天会获得此access_token,他可以访问所有受保护的资源!

但是,如果您具有refresh_token,则access_token的生存时间很短,因此,黑客很难破解您的access_token,因为它会在短时间内失效。 不仅可以通过使用refresh_token来获取Access_token,而且还可以使用黑客没有的client_id和client_secret来获取。

答案 11 :(得分:2)

授权服务器保留刷新令牌。访问令牌是自包含的,因此资源服务器可以在不存储的情况下对其进行验证,从而节省了验证时的检索工作。 讨论中缺少的另一点是来自rfc6749#page-55

  

“例如,授权服务器可以使用刷新令牌   每次访问都会发出新刷新令牌的轮换   令牌刷新响应。之前的刷新令牌无效   由授权服务器保留。如果是刷新令牌   被攻击者和攻击者共同攻击并随后使用   合法客户端,其中一个将呈现无效的刷新   令牌,它将通知授权服务器违规。“

我认为使用刷新令牌的重点在于即使攻击者以某种方式设法获得刷新令牌,客户端ID和秘密组合。如果每次刷新请求都会产生新的访问令牌和刷新令牌,则可以跟踪从攻击者获取新访问令牌的后续调用。

答案 12 :(得分:0)

让我们考虑一个系统,其中每个用户都链接到一个或多个角色,每个角色都链接到一个或多个访问权限。可以缓存此信息以获得更好的API性能。但是,用户和角色配置可能会发生变化(例如,可能会授予新访问权限或撤销当前访问权限),这些应该反映在缓存中。

我们可以为此目的使用访问和刷新令牌。使用访问令牌调用API时,资源服务器会检查缓存的访问权限。如果有任何新的访问授权,则不会立即反映。一旦访问令牌到期(例如在30分钟内)并且客户端使用刷新令牌生成新的访问令牌,就可以使用来自DB的更新的用户访问权限信息来更新缓存。

换句话说,我们可以使用访问令牌将昂贵的操作从每个API调用移动到使用刷新令牌生成访问令牌的事件。

答案 13 :(得分:0)

  

首先,客户端通过授予授权来授权服务器进行身份验证。

     

然后,客户端通过提供访问令牌向资源服务器请求受保护资源。

     

资源服务器验证访问令牌并提供受保护资源。

     

客户端通过授予访问令牌向资源服务器发出受保护资源请求,资源服务器在其中验证它并提供请求(如果有效)。此步骤将一直重复,直到访问令牌过期。

     

如果访问令牌过期,则客户端通过授权服务器进行身份验证,并通过提供刷新令牌来请求新的访问令牌。如果访问令牌无效,资源服务器会将无效令牌错误响应发送回客户端。

     

客户端通过授予刷新令牌对授权服务器进行身份验证。

     

然后,授权服务器通过验证客户端验证刷新令牌,并发出新的访问令牌(如果有效)。

答案 14 :(得分:0)

据我所知,如果您需要撤销访问权限,刷新令牌只是为了节省性能和成本。

例如 1:不实现刷新令牌;仅实现长期访问令牌: 如果用户滥用服务(例如:不支付订阅费用),您需要能够撤销访问令牌 => 您需要在每个需要访问令牌的 API 调用上检查访问令牌的有效性,这会很慢,因为它需要进行数据库查找(缓存可以提供帮助,但这会更复杂)。

例如 2:实施刷新令牌和短期访问令牌: 如果用户滥用服务(例如:不支付订阅费用),您需要能够撤销访问令牌 => 短期访问令牌将在短暂的白色(例如 1 小时)后到期,用户需要获得一个新的访问令牌,因此我们不需要对每个需要访问令牌的 API 调用进行验证。您只需要在从刷新令牌生成访问令牌时验证用户。对于坏用户,如果无法生成访问令牌,您可以注销该用户。当用户尝试重新登录时,验证将再次运行并返回错误。