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

Why Does OAuth v2 Have Both Access and Refresh Tokens?

提问人:dave mankoff 提问时间:8/15/2010 最后编辑:Super Kai - Kazuya Itodave mankoff 更新时间:9/5/2023 访问量:299533

问:

OAuth 2.0 协议草案的第 4.2 节指出,授权服务器既可以返回 an(用于使用资源验证自己身份)也可以返回 ,这纯粹用于创建新的:access_tokenrefresh_tokenaccess_token

https://www.rfc-editor.org/rfc/rfc6749#section-4.2

为什么两者兼而有之?为什么不让最后的和没有一个?access_tokenrefresh_tokenrefresh_token

安全性 oauth-2.0 oauth access-token 刷新令牌

评论


答:

548赞 catchdave 8/27/2011 #1

刷新令牌的理念是,如果访问令牌被泄露,因为它是短暂的,攻击者滥用它的窗口有限。

如果刷新令牌遭到破坏,则毫无用处,因为攻击者除了刷新令牌外,还需要客户端 ID 和机密才能获得访问令牌。

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

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

这里有一个很好的话题,讨论刷新令牌的使用:OAuth Archives

上面引用一句话,谈到了刷新令牌的安全目的:

刷新令牌...降低长期access_token泄漏的风险(在不安全的资源服务器上的日志文件中查询参数、beta 版或编码不当的资源服务器应用程序、将access_token放入 cookie 中的非 https 站点上的 JS SDK 客户端等)

评论

15赞 AlexGad 7/12/2012
Catchdave 是对的,但我想我要补充一点,自从他最初的回复以来,事情已经发生了变化。SSL的使用现在是可选的(当catchdave回答时,这可能仍在争论中)。例如,MAC 令牌(目前正在开发中)提供了使用私钥对请求进行签名的功能,因此不需要 SSL。因此,刷新令牌变得非常重要,因为您希望拥有短期的 mac 令牌。
71赞 Jamsheed Kamarudeen 1/5/2015
“如果刷新令牌遭到破坏,则毫无用处,因为除了刷新令牌之外,攻击者还需要客户端 ID 和密钥才能获得访问令牌。”但是客户端 ID 和 secret 也存储在设备中,不是吗?因此,有权访问设备的攻击者可以获取它们。那为什么呢?在这里,github.com/auth0/lock/wiki/Using-a-Refresh-Token,写到丢失刷新令牌意味着,他可以请求任意数量的身份验证令牌,可能不在谷歌的场景中,但是如果我正在实现自己的 oauth2 服务器呢?
60赞 sp00m 10/2/2015
“除了刷新令牌之外,攻击者还需要客户端 ID 和密码才能获取访问令牌”:那么使用刷新令牌和简单地重新登录有什么区别?
48赞 Marek Dec 12/22/2015
刷新令牌可由第三方使用,该第三方可以在不了解用户凭据的情况下续订访问令牌。
41赞 machine yearning 9/15/2016
@KevinWheeler 否,客户端 ID 和密码是 OAuth 客户端的凭据,而不是用户的凭据。在谈论 OAuth 时,“客户端”通常是与授权或资源 API 服务器(例如 facebook 身份验证提供商)接口的服务器(例如 stackoverflow Web 服务器)。用户的凭据仅在用户和 OAuth API 服务器之间传递,客户端永远不会知道。客户端密码仅从客户端传递到 OAuth API 服务器,用户永远不会知道。
89赞 B T 8/3/2012 #2

这两个答案都没有触及刷新令牌存在的核心原因。显然,您始终可以通过将客户端凭据发送到身份验证服务器来获取新的访问令牌/刷新令牌对 - 这就是您首先获取它们的方式。

因此,刷新令牌的唯一用途是限制使用通过网络发送到身份验证服务的客户端凭据。访问令牌的 TTL 越短,客户端凭据用于获取新访问令牌的频率就越高,因此攻击者破坏客户端凭据的机会就越大(尽管如果使用非对称加密发送客户端凭据,这可能非常困难)。因此,如果您有一次性刷新令牌,则可以在不损害客户端凭据的情况下将访问令牌的 TTL 任意小。

评论

29赞 Rots 6/2/2014
这很有趣,因为在 Google 的情况下,当您请求刷新令牌时,您还会发送客户端 ID 和客户端密钥。所以无论如何,你每小时都在妥协。
6赞 Rhubarb 6/3/2015
“唯一目的”——不洗。使访问令牌的 TTL 与想象的刷新令牌的 TTL 一样长,将实现相同的结果。
12赞 Kevin Christopher Henry 7/5/2016
由于该标准要求客户端凭据与刷新令牌一起发送,因此此答案的前提是错误的。“因为刷新令牌通常是用于请求其他访问令牌的持久凭据......客户端必须向授权服务器进行身份验证。另请参阅@Rots的评论。
18赞 Andreas Lundgren 10/10/2016
A) 我认为您混淆了客户端密钥和用户密钥。客户端密钥从不从用户设备发送,仅从访问后端应用程序发送到提供数据的后端应用程序。B) 允许为公共客户端(无法保留客户端密钥的客户端,例如本机或 javascript 应用程序)授予密码的 oAuth 服务器也将为该公共客户端提供刷新令牌授予,因此在刷新令牌时无需发送客户端密钥。C) refresh-token 为后端提供“hart-beat”,用于检查用户的有效性!
3赞 Hans Z. 5/6/2017
这个答案是错误的,因为安德烈亚斯·伦德格伦(Andreas Lundgren)说
20赞 Phil 8/19/2012 #3

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

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

刷新令牌基本上适合普通网站可能选择在一小时左右后定期重新验证用户身份的地方(例如银行网站)。它目前使用率不高,因为大多数社交网站不会重新验证网络用户,那么他们为什么要重新验证客户端呢?

评论

4赞 James 11/6/2014
“刷新令牌仅允许客户端重新进行身份验证...”是这里的一个重要方面。
668赞 Roman Imankulov 10/15/2012 #4

由 Catchdave 提供的讨论链接还有 Dick Hardt 提出的另一个有效观点(原始的、死链接),我认为除了上面写的内容之外,这里还值得一提:

我记得刷新令牌是为了安全和吊销。 <...>

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

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

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

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

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

服务器允许客户端通过颁发令牌在一组预定义的范围内访问用户数据。由于我们希望保持令牌可撤销,因此我们必须将令牌与设置或取消设置的标志“revoked”一起存储在数据库中(否则,您将如何使用独立的令牌?数据库可以包含与记录一样多的内容。然后,每个 API 请求都必须命中数据库。尽管对执行 O(1) 的此类数据库进行查询是相当微不足道的,但单点故障本身可能会对系统的可伸缩性和性能产生负面影响。len(users) x len(registered clients) x len(scopes combination)

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

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

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

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

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

权衡

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

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

  2. 客户端逻辑的复杂性。

    没有刷新令牌

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

    使用刷新令牌

    • 使用访问令牌发送 API 请求
    • 如果访问令牌无效,请尝试使用刷新令牌进行更新
    • 如果刷新请求通过,请更新访问令牌并重新发送初始 API 请求
    • 如果刷新请求失败,请要求用户重新进行身份验证

我希望这个答案确实有意义,并帮助人们做出更深思熟虑的决定。我还想指出,一些著名的 OAuth2 提供商,包括 github 和 foursquare,采用没有刷新令牌的协议,并且似乎对此感到满意。

评论

7赞 kosnkov 11/12/2014
@RomannImankulov 如果我理解正确,我们可以将令牌保存到数据库中,并在我们想要撤销访问权限时随时删除它们,那么为什么不自己保存访问令牌呢?
48赞 Roman Imankulov 11/14/2014
@kosnkov我帖子的简短版本是,如果您将访问令牌保存在数据库中,则在对 API 的每个请求中都会命中数据库(在您的特定情况下,这可能是也可能不是问题)。如果保存刷新令牌并使访问令牌保持“独立”,则仅当客户端决定刷新访问令牌时才访问数据库。
19赞 Bitcoin Cash - ADA enthusiast 9/21/2015
就我个人而言,我不喜欢这种不攻击数据库以获得性能的方法,如果它会损害安全性(即使只是在窗口的时间跨度内)。如有必要,应该能够立即撤销access_token,因为我们几乎总是在处理敏感的用户信息(否则我们可能不会首先使用 OAuth)。我想知道像Facebook和谷歌这样的大公司使用哪种方法。
3赞 aderchox 2/27/2023
“尽管如此,我们仍然必须保留刷新令牌的数据库” -> 不是吗?我们可以只保留一个访问令牌数据库,但只有在收到过期的访问令牌后才点击它!右?或者我错过了什么。
16赞 bitcoder 4/28/2015 #5

为了进一步简化 B T 的答案:如果通常不希望用户再次键入凭据,但仍希望能够撤消权限(通过撤消刷新令牌),请使用刷新令牌

不能吊销访问令牌,只能吊销刷新令牌。

评论

1赞 Atieh 2/23/2016
您可以吊销访问令牌,这需要再次登录以获取另一个访问令牌或使用刷新令牌获取另一个访问令牌。如果刷新令牌无效,用户必须重新进行身份验证才能获取新的访问令牌以及新的刷新令牌。
12赞 bitcoder 2/23/2016
我不同意。访问令牌由身份验证服务器颁发,使用到期日期进行签名,然后发送到客户端。当客户端将该令牌发送到资源服务器时,资源服务器不会联系身份验证服务器来验证令牌;它只查看(已签名和未篡改)令牌中的到期日期。因此,无论您在身份验证服务器上尝试“撤销”什么,资源服务器都不在乎。有些人将客户端注销称为撤销(即客户端删除其令牌),但恕我直言,这是误导性的术语 - 我们想在服务器上“撤销”令牌,而不是客户端
1赞 bitcoder 2/23/2016
并不是说你不能编写自定义代码来忽略某些令牌(就像这里 stackoverflow.com/questions/22708046/...),但这样做可能涉及每次客户端进行调用时从资源服务器到 oauth 服务器/数据库的一些网络行程。您可以通过使用刷新令牌来避免这些调用,我认为这更符合 oauth 作者的意图。
43赞 Manicode 8/31/2015 #6

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


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

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

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

欲了解更多信息,请阅读 http://oauth.net/articles/authentication/

评论

2赞 sleske 5/11/2020
这似乎是关于 OpenID Connect 和身份验证的,所以我不明白这如何回答这个问题,这是关于令牌刷新的动机。
14赞 heymega 1/19/2016 #7

为什么不让access_token和refresh_token一样持久 没有refresh_token?

除了其他人提供的精彩答案之外,我们使用刷新令牌还有另一个原因,这与声明有关。

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

如果我们更频繁地刷新令牌,显然会给身份服务带来更大的压力;但是,我们得到了更准确和最新的索赔。

评论

4赞 Kevin Christopher Henry 7/5/2016
将此类“声明”放在访问令牌中将是一种不寻常的不良做法。如规范中所述,访问令牌“通常对客户端是不透明的”。您是否有执行此操作的 OAuth 提供程序示例?
4赞 svlada 8/16/2016
@heymega 当用户角色从 ADMIN 降级为 REGULAR_USER 时,预期用户角色需要立即撤销,而不是在access_token过期时撤销。因此,看起来在每个请求上访问数据库是不可避免的。
2赞 e_i_pi 6/1/2017
@svlada我想在这种情况下,将实体从 ADMIN 降级为 REGULAR_USER 的应用程序(在同一过程中)也需要撤销相应的令牌。也就是说,如果我们知道索赔将发生变化,我们不会等待到期,我们会立即撤销
86赞 Adversus 3/4/2016 #8

为了消除一些混淆,您必须了解客户端密码和用户密码的角色,它们非常不同。

客户端是一个应用程序/网站/程序/...,由服务器提供支持,它希望使用第三方身份验证服务对用户进行身份验证。客户端密码是此客户端和身份验证服务器都知道的(随机)字符串。使用此密钥,客户端可以在身份验证服务器中标识自己,并接收请求访问令牌的授权

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

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

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

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

这清楚地表明了差异:在刷新时,客户端使用其客户端密码接收刷新访问令牌的授权,因此可以使用刷新令牌而不是用户 ID + 密码重新验证用户身份。这有效地防止了用户必须重新输入他/她的密码。

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

评论

0赞 downvoteit 1/3/2023
我不明白最后一句话。由于 TLS,客户端 ID 和客户端密钥也可能丢失,可能不那么容易丢失。大多数情况下,它们会被一些粗心的公共应用程序(如移动应用程序和网站)丢失,这些应用程序和网站将这些暴露给世界。考虑到这一点,刷新令牌唯一要做的就是减少用户名:密码链在其他可能粗心的服务之间的网络通信中的暴露。
0赞 Adversus 1/9/2023
网站不太可能丢失这些,因为它们仅在后端处理,而不是在前端处理。移动应用程序确实是另一回事。
0赞 downvoteit 1/9/2023
这并不常见,但我有几个这样的 Web 应用程序前端需要修复。也许是因为授权类型(单步)比(两步)更容易实现。passwordauthorization code
273赞 laalaguer 6/19/2016 #9

尽管上面有很好的答案,但我作为一名安全硕士生和程序员,以前在eBay工作过,当时我研究了买家保护和欺诈,可以说将访问令牌和刷新令牌分开,在骚扰频繁输入用户名/密码的用户和保持权力以撤销对潜在滥用您的服务的访问权限之间取得了最佳平衡

想想这样的场景。您向用户颁发了 3600 秒的访问令牌,刷新令牌的时间比一天长得多。

  1. 用户是一个用户,他在家里,在他的 iPhone 上打开/关闭您的网站购物和搜索。他的 IP 地址不会更改,并且您的服务器负载非常低。比如每分钟有 3-5 个页面请求。当他在访问令牌上的 3600 秒结束时,他需要一个带有刷新令牌的新令牌。我们在服务器端检查他的活动历史记录和IP地址,认为他是一个人,并表现自己。我们授予他一个新的访问令牌,以继续使用我们的服务。用户在达到刷新令牌本身的一天生命周期之前,无需再次输入用户名/密码。

  2. 用户是一个粗心的用户。他住在美国纽约,他的病毒程序被关闭,并在波兰被黑客入侵。当黑客获得访问令牌和刷新令牌时,他会尝试冒充用户并使用我们的服务。但是在短寿命访问令牌过期后,当黑客尝试刷新访问令牌时,我们在服务器上注意到用户行为历史记录中的 IP 发生了巨大变化(嘿,这家伙在美国登录,现在在波兰刷新访问仅仅 3600 秒???)。我们终止刷新过程,使刷新令牌本身失效,并提示再次输入用户名/密码。

  3. 用户是恶意用户。他打算滥用我们的服务,使用机器人每分钟调用 1000 次我们的 API。他可以很好地做到这一点,直到 3600 秒后,当他尝试刷新访问令牌时,我们注意到了他的行为,并认为他可能不是人类。我们拒绝并终止刷新过程,并要求他再次输入用户名/密码。这可能会破坏机器人的自动流程。至少让他不舒服。

您可以看到,当我们试图平衡我们的工作、用户体验和令牌被盗的潜在风险时,刷新令牌表现得非常完美。您在服务器端的看门狗可以检查多个 IP 更改、API 调用频率,以确定用户是否是好用户。

另一个说法是,您还可以尝试通过在每个 api 上实施调用基本 IP 看门狗或任何其他措施来限制被盗令牌/滥用服务的损害控制。但这很昂贵,因为您必须读取和写入有关用户的记录,并且会减慢服务器响应速度。

评论

98赞 Evert 10/20/2016
这些是一些很棒的策略和想法,但我在您的答案中没有看到任何本质上需要使用刷新令牌的内容。所有这些功能都可以仅使用访问令牌来实现。
17赞 Avi Cherry 12/6/2016
@Evert,同时使用访问令牌和刷新令牌的好处之一是访问令牌的生存期可能很短,因此,在不与最初颁发它们的服务器核实的情况下无条件信任它们并不过分的安全隐患。这允许您扩展基础结构,以便其非关键部分可以信任存储在(签名)令牌中的信息,而无需直接访问用户的帐户信息。
10赞 Rick Jolly 5/16/2017
@Avi Cherry - 是的,访问令牌可以是短暂的,如果用户仍被视为有效,也可以刷新它。不需要刷新令牌即可执行此操作。
26赞 tne 9/5/2017
我相信这个答案假设我们不希望资源服务器自己进行高级访问控制(例如,根据各种数据库检查 IP 活动等),相反,它们只能依赖于完全隔离地验证访问令牌。虽然这在规模上可能很明显(出于性能原因),但考虑到其他帖子和评论的混乱,对于这里的每个人来说显然并不明显。这是一篇很好的帖子,信息很好,但我觉得它大大错过了原始问题的重点。我建议至少明确上述假设。
0赞 Simon_Weaver 2/4/2019
@RickJolly 关于“访问令牌可以是短暂的,如果用户仍然被认为是有效的,它也可以刷新”——我认为回答者得到的是客户可能在 ebay 上浏览 - 比如说鞋子 - 在 3 小时内浏览 4 或 24 次。登录必须保持“有效”一整天,否则用户将非常沮丧地不得不继续登录。如果他们在移动设备上,那么如果用户在该浏览器选项卡中不处于活动状态,则不会“刷新”任何内容。但是他的访问令牌获取起来比较昂贵,只需要刷新 3 或 4 次。
3赞 Saptarshi Basu 1/14/2017 #10

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

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

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

1赞 user8288060 9/7/2017 #11

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

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

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

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

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

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

然后,授权服务器通过对客户端进行身份验证来验证刷新令牌,并颁发新的访问令牌(如果有效)。

评论

0赞 Simon_Weaver 2/4/2019
这实际上并没有提到刷新令牌的来源。我假设第二段应该说?access token + refresh token
4赞 Kraming 11/17/2017 #12

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

“例如,授权服务器可以使用刷新令牌 每次访问时都会颁发新的刷新令牌的轮换 令牌刷新响应。以前的刷新令牌已失效,但 由授权服务器保留。如果刷新令牌是 遭到入侵,随后被攻击者和 合法客户端,其中一个客户端将显示无效的刷新 令牌,这将通知授权服务器违规行为。

我认为使用刷新令牌的全部意义在于,即使攻击者以某种方式设法获得刷新令牌、客户端 ID 和密钥组合。通过后续调用从攻击者那里获取新的访问令牌,可以跟踪每个刷新请求是否导致新的访问令牌和刷新令牌。

评论

0赞 Simon_Weaver 2/4/2019
我认为这是非常重要的一点:-)在某种程度上,它也使这里的论点无效 auth0.com/docs/tokens/refresh-token/current#restrictionsA Single-Page Application (normally implementing Single-Page Login Flow) should not under any circumstances get a Refresh Token. The reason for that is the sensitivity of this piece of information. You can think of it as user credentials, since a Refresh Token allows a user to remain authenticated essentially forever. Therefore you cannot have this information in a browser, it must be stored securely.
6赞 Tạ Anh Tú 10/3/2018 #13

假设你做了最后很长的时间,并且没有,所以在一天之内,黑客得到了这个,他可以访问所有受保护的资源!access_tokenrefresh_tokenaccess_token

但是如果你有,它的生存时间很短,所以黑客很难破解你的,因为它会在短时间内失效。 只能通过使用 only 而且 by 和 来检索,这是黑客所没有的。refresh_tokenaccess_tokenaccess_tokenAccess_tokenrefresh_tokenclient_idclient_secret

评论

2赞 mfaani 9/3/2019
“不仅使用refresh_token,还client_id和client_secret,这是黑客所没有的。”1. 假设它只是访问令牌,那么 Hacker 不是还需要client_id和client_secret吗?2.如果黑客是一个好的黑客,那么他也可以破解client_id并client_secret。不管那部分如何,黑客攻击其他东西对比较来说应该无关紧要,因为如果很难破解,那么在仅使用访问令牌的情况下也很难破解......长话短说,你不是在比较相同的情况。你把它们混合在一起
58赞 mfaani 8/15/2019 #14

这个答案是在两位高级开发人员(John Brayton 和 David Jennes)的帮助下完成的。

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

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

一栋建筑有 80 扇门。所有门都用同一把钥匙打开。密钥每 30 分钟更改一次。在 30 分钟结束时,我必须将旧钥匙交给钥匙制造商并获得新钥匙。

如果我是黑客并拿到了你的钥匙,那么在 30 分钟结束时,我会把它快递给钥匙制作者并得到一个新钥匙。无论钥匙如何变化,我都能够连续打开所有门。

问题:在这 30 分钟内,我有多少次针对密钥的黑客攻击机会?我有 80 次黑客攻击机会,每次你使用密钥时(可以把它想象成发出网络请求并传递访问令牌来识别你自己)。这就是 80 倍的攻击面。

现在让我们看一下相同的示例,但这次让我们假设有一个刷新键。

一栋建筑有 80 扇门。所有门都用同一把钥匙打开。密钥每 30 分钟更改一次。若要获取新密钥,我无法传递旧的访问令牌。我只能传递刷新键。

如果我是黑客并拿到了你的密钥,我可以使用它 30 分钟,但在 30 分钟结束时,将其发送给密钥制作者没有任何价值。如果我这样做,那么密钥制作者只会说“这个令牌已过期。您需要刷新令牌。为了能够扩展我的黑客攻击,我必须将快递员破解给密钥制造者。快递员有一个不同的密钥(可以将其视为刷新令牌)。

问题:在这 30 分钟内,我有多少次针对刷新密钥的黑客攻击机会?80?不。我只有 1 次黑客攻击机会。在快递员与钥匙制作人沟通期间。这就是 1 倍的攻击面。 我确实有 80 次针对密钥的黑客攻击机会,但 30 分钟后就不好了。


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

访问令牌泄漏是不好的,但一旦过期,它对攻击者就不再有用。刷新令牌泄漏的情况要糟糕得多,但可能性可能较小。(我认为刷新令牌泄漏的可能性是否远低于访问令牌泄漏的可能性存在疑问,但这就是这个想法。

要点是,访问令牌将添加到您发出的每个请求中,而刷新令牌仅在刷新流期间使用 因此,MITM看到令牌的机会较小

频率有助于攻击者。类似 Heartbleed 的潜在安全漏洞、客户端中的潜在安全漏洞以及服务器中的潜在安全漏洞都使泄漏成为可能。

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

分隔有利于安全。

最后但并非最不重要的一点是,刷新令牌可以轮换。这意味着“每次客户端请求将刷新令牌交换为新的访问令牌时,都会返回一个新的刷新令牌”。随着刷新令牌的不断交换和失效,威胁会降低。举个例子:令牌通常在 TTL 后过期,通常一个小时。

刷新令牌并非总是如此,但通常会在使用时被吊销并颁发新的令牌。这意味着,如果出现网络故障,则在检索新的刷新令牌时,下次发送该刷新令牌时,该令牌将被视为已吊销,必须登录。

有关轮换的更多信息,请参阅此处此处

总结

  • 降低频率
  • 划分
  • 令牌的轮换(更快的失效)和更精细的管理(过期时间或发出的请求数)。

所有这些都有助于减轻威胁

对于这个问题的另一种看法,请参阅这个很棒的答案


刷新令牌不是关于什么的?

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

评论

13赞 Vmxes 10/13/2021
为什么攻击者获取刷新令牌比获取访问令牌更难?使用 HTTPS 可以在传输过程中提供保护,但我需要将它们都存储在浏览器中,以防 SPA。因此,攻击者可以同时对它们进行强化。我错过了什么吗?
2赞 mfaani 10/13/2021
@Vmxes从这个角度来看,我认为它们没有区别。但从浏览器、路由器、ISP、VPN 等之间的传输层上下文来看,访问令牌每小时可以传递 1000 次,而刷新令牌只能传递一次。
1赞 XouDo 12/8/2021
在此示例中,使用旧令牌(旧密钥)获取新令牌(新密钥)。这不是在没有刷新令牌机制的情况下获取访问令牌的方式:每次需要新的访问令牌时,都必须发回密码。
1赞 Ulvi 1/14/2022
同时拥有 Access 和 Refresh 令牌意味着攻击者有更多机会通过猜测其中一个令牌来访问用户帐户。如果不是这种情况,为什么攻击者能够从客户端破解您的访问令牌,那么他/她将无法破解您的刷新令牌。
2赞 Veita 9/22/2022
攻击者可以访问访问令牌和刷新令牌。关键是 - 使用长期访问令牌,受害者和攻击者都可以继续运行。但是,对于短期访问令牌和刷新令牌轮换,刷新令牌使用两次后,刷新令牌将停止运行,并且双方都会失去访问权限。
2赞 Anusha Dharmasena 6/16/2021 #15

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

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

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

2赞 KJ Sudarshan 10/22/2021 #16

刷新令牌和访问令牌只是术语。

这个小类比可以帮助巩固使用访问令牌和刷新令牌背后的基本原理:

假设 Alice 通过邮寄方式向 Bob 发送了一张支票,该支票可以在签发后 1 小时内兑现(假设),否则银行将不会兑现。 但爱丽丝还在给银行的帖子中附上了一张纸条,要求银行接受并兑现支票,以防支票延迟(在规定的范围内)

Bob 收到这张支票时,如果他看到这张支票被篡改(令牌篡改),他自己将丢弃这张支票。如果没有,他可以把它带到银行兑现。 在这里,当银行注意到发行时间已超过 1 小时时限,但看到 Alice 的签名票据,要求银行在规定的延迟范围内兑现。

看到这张便条后,银行会尝试验证已签名的邮件,并检查 Alice 是否仍然拥有正确的权限。如果是,银行将兑现支票。 Bob 现在可以向 Alice 确认这一点。

虽然不是很准确,但这个类比可以帮助你注意到处理交易所涉及的不同部分:

  • Alice (发件人 - 客户)
  • Bob (接收方 - 资源服务器)
  • 银行(授权服务器)
  • 验证过程(数据库访问)
  • 支票(存取令牌)
  • 备注(刷新令牌)

主要是,我们希望减少对身份验证服务器的 API 调用次数,并最终减少对数据库的 API 调用,以优化可伸缩性。我们需要在便利性和安全性之间取得适当的平衡

注意:让 Auth 服务器比链中的资源服务器更早响应请求当然更常见。

1赞 raisercostin 1/24/2022 #17

由于刷新令牌和访问令牌是加载了大量语义的术语,因此术语转换可能会有所帮助?

  • 可撤销令牌 - 必须使用授权服务器检查的令牌
    • 可以链接(参见 RTR - 刷新令牌轮换)
    • 可用于创建不可撤销的令牌,但也可以直接使用(当卷较小且检查不会成为负担时)
    • 可以长期存在,但这取决于用户必须为凭据(用户名/密码)烦恼以获取新凭据的频率
    • 可以在 RTR 或任何其他可疑行为上失效
  • 不可撤销令牌 - 自包含的令牌,不需要通过授权服务器进行检查
    • 对于大数据、分布式服务器/API 调用的水平扩展很有用
    • 应该是短暂的(因为不可撤销)

在 2020 年,人们开始接受刷新令牌也可以存在于浏览器中(最初是为后端系统提供的)——参见 https://pragmaticwebsecurity.com/articles/oauthoidc/refresh-token-protection-implications。正因为如此,重点从“可刷新性”(在没有用户的情况下后端将如何延长对 API 的访问)转移到“可撤销性”。

因此,对我来说,将刷新令牌读取为可撤销令牌,将访问令牌读取为不可撤销令牌(可能是快速过期的不可撤销令牌)看起来更安全。

作为 2021 年良好实践的旁注,系统始终可以从可撤销的令牌开始,并在授权服务器的压力增加时转为不可撤销。

0赞 aderchox 3/30/2022 #18

有时,用户的访问令牌可能会在用户一无所知的情况下被盗。由于用户不知道攻击,他们将无法手动通知我们。然后,例如,15 分钟和一整天之间将存在巨大差异,关于我们给攻击者完成其攻击的时间(机会)。因此,这就是我们需要每隔“短时间”(例如每 15 分钟)自行“刷新”访问令牌的原因,我们不想长时间(例如一整天)推迟这样做。因此,OP 在问题中所说的显然不是一个选项(只要刷新令牌的到期时间,就会延长访问令牌的到期时间)。

我们至少有这三个选项(我现在能想到):

  1. 要求每个用户每隔一小段时间重新输入其凭据,以便为他们提供新的访问令牌。但显然,这不是一个受欢迎的选择,因为它会给用户带来麻烦。

  2. 不要使用单独的令牌进行刷新,而是更新同一访问令牌的到期时间,一旦发出重复的到期延期请求,就将其计为潜在的令牌盗窃,使令牌失效,并让用户重新证明自己。然而,这种方式也有一个很大的缺点,如果访问令牌被盗,只要真正的所有者没有重新访问我们的服务(甚至可能是“几天”),我们就不会意识到盗窃,只要我们允许,攻击者就可以扩展被盗的访问令牌。现在将此与下一个选项进行比较,该选项使用“刷新令牌”。

  3. 使用第二个令牌,称为“刷新令牌”,是我们的下一个选项。专门为延长用户登录目的而添加此令牌至少具有以下三个好处: 1. 无需像发送访问令牌那样频繁地发送此更敏感的令牌(即对受保护终结点的“每个”请求)。2. 除了刷新令牌之外,我们可以请求更多信息来颁发新的访问令牌,例如 API 服务器的客户端密钥。因此,即使刷新令牌被盗,攻击者也无法使用它请求新的访问令牌。3. 我们隐含地告诉开发人员,刷新令牌是“更敏感的令牌”,他们必须更加注意其安全性,例如,将其保持在攻击者的客户端代码无法访问的方式,例如,在带有标签的 cookie 中。httpOnly

HttpOnly Cookie 是添加到浏览器 Cookie 的标记,用于阻止客户端脚本访问数据。

在生成 Cookie 时使用 HttpOnly 标志有助于降低客户端脚本访问受保护 Cookie 的风险。HttpOnly Cookie 于 2002 年由 Microsoft Internet Explorer 开发人员首次为 Internet Explorer 6 SP1 实现。来源(谢谢IE!

因此,虽然攻击者仍然能够窃取这两种代币,但与其他选项相比,我们在一定程度上降低了风险。

4赞 Bernard Wiesner 4/20/2022 #19

这一切都是为了扩展和保持资源服务器无状态。

  • 您的服务器/资源服务器
    • 服务器是无状态的,这意味着不检查任何存储以非常快速地响应。为此,请使用公钥验证令牌的签名。

    • 检查每个请求。access_token

    • 通过仅检查 的签名和到期日期,响应速度非常快,并允许缩放。access_token

    • access_token应该有很短的到期时间(几分钟),因为没有办法撤销它,如果它被泄漏,损害是有限的。

  • 身份验证服务器/OAuth 服务器
    • 服务器不是无状态的,但它是可以的,因为请求要少得多。
    • 仅在过期时进行检查。(例如每 2 分钟一次)refresh_tokenaccess_token
    • 请求速率远低于资源服务器。
    • 将刷新令牌存储在数据库中,并可以撤销它。
    • refresh_token可能有很长的到期时间(几周/几个月),如果它被泄露,有一种方法可以撤销它。

不过,有一个重要的注意事项,身份验证服务器的请求要少得多,因此可以处理负载,但是可能存在存储问题,因为它必须存储所有,如果用户急剧增加,这可能会成为一个问题。refresh_tokens

评论

1赞 aderchox 2/27/2023
但是访问令牌仍然可以用于两者?在资源服务器上,只有当用户的访问令牌到期时,拒绝它就足够了(恶意用户不得篡改这个过期时间,b/c 资源服务器有公钥,可以检查访问令牌中数据的签名和“诚实性”),一旦访问令牌被拒绝,用户必须将其提供给身份验证服务器以延长同一访问令牌的到期时间尚未撤销,或者用户没有任何可疑的 IP/位置更改等。
0赞 Bernard Wiesner 2/27/2023
@aderchox是的,正如您描述的那样,它在资源和身份验证服务器上都使用了。
1赞 Sandeep Amarnath 10/11/2022 #20

我在这里得到了一些额外的资源,这些资源澄清了我们为什么需要refresh_token的某些事情。这些资源的一些关键点如下:

  • 在现实世界中,最好有单独的服务器称为 和authServerresourceServer/s
    • authServer - 仅用于身份验证和授权。这个服务器的责任是发出,也和用户refresh tokenaccess tokenloginlogout
    • resourceServer - 此服务器(也可以是多个服务器负载平衡)提供受保护的数据。例如,在电子商务项目中,此数据可以像 ,等等productsreviews
  • 其中一个用途是,我们不必每次需要新的 .这应该只在第一次完成(当你还没有的时候),并且现在会从 authServer 获得新的,这样你就可以继续向受保护的 resourceServer 发出请求。这里的优点是,用户不必每次都提供凭据,因此用户的用户名和密码不容易泄露。refresh_tokenusername and password (credentials)access_tokenrefresh_tokenrefresh_tokenaccess_token
  • 另一个主要用途是,假设与现实世界中的 resourceServer(第三方服务,如 auth0oktaazure 等或您自己的实现)相比,您的 authServer 受到非常保护。您只会将 your 发送到 resourceServer(获取数据),而永远不必发送到 resourceServer 。因此,当您发送到 resourceServer 时,很有可能有一个黑客拦截您的 resourceServer(因为它不像 authServer 那样安全),他可以访问您短暂的。refresh_tokenaccess_tokenrefresh_tokenaccess_tokenaccess_token
    • 因此,它的寿命很短(如 30 分钟)。请记住,当它到期时,您将发送到 authServer(它比 resourceServer 非常安全)以获取新的 .由于您不会在任何时候将 发送到 resourceServer,因此拦截 resourceServer 的黑客不可能获得您的 .如果您作为开发人员仍然怀疑您的用户也可能被黑客入侵,那么您可以注销所有用户(使所有用户无效),这样用户将再次登录(提供用户名和密码)以获得新的 +,事情将再次走上正轨。access_tokenaccess_tokenrefresh_tokenaccess_tokenrefresh_tokenrefresh_tokenrefresh_tokenrefresh_tokenrefresh_tokenaccess_token

一些有用的资源

带和不带刷新令牌的工作流 - Youtube

JWT 认证代码示例 - Node JS - Youtube

0赞 kaqqao 9/2/2023 #21

我对任何排名靠前的答案都不满意,所以我会把自己的答案扔进去。

访问令牌是要传递的。到一个或多个后端(例如 StackOverflow),这些后端又可能会将其转发到其他服务等(因为微服务风靡一时),如果其中任何一个粗心大意并记录或以其他方式暴露您的令牌,或者是主动恶意的 - 您就有麻烦了。因此,您可以缩短访问令牌的生存期,以限制爆炸半径。

但是,你有一个单独的(生存期更长的)令牌,你只发送给你已经信任的单个服务——与你一开始向你颁发访问令牌的服务相同(比如谷歌,或者你用来登录 StackOverflow 的任何服务)。你使用这个令牌来获得新的短期令牌,再次传递给你不太信任的第三方。

这一切都意味着,如果您自己的设备或应用程序或您自己受到威胁,刷新令牌根本没有任何作用(通常任何其他身份验证机制也是如此)。但是,如果 StackOverflow 遭到入侵,则只会公开短期访问令牌,因为 StackOverflow 永远不会看到长期存在的刷新令牌。而关于每个代币使用频率的整个戏剧充其量只是一条红鲱鱼。这完全取决于谁可以看到哪个代币。