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

dav*_*off 603 security oauth access-token refresh-token

OAuth 2.0协议草案的4.2节指出授权服务器可以返回a access_token(用于向资源验证自己)以及a refresh_token,它纯粹用于创建新的access_token:

https://tools.ietf.org/html/rfc6749#section-4.2

为什么两者都有?为什么不只是做到access_token最后只要refresh_token没有refresh_token

Rom*_*lov 529

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

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

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

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

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

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

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

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

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

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

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

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

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

权衡

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

  1. 窗户".事件"用户撤销访问"和"访问保证被撤销"之间的时间范围.

  2. 客户逻辑的复杂性.

    没有刷新令牌

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

    使用刷新令牌

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

我希望这个答案确实有意义并帮助某人做出更周到的决定.我还要注意一些着名的OAuth2提供程序,包括github和foursquare,采用没有刷新令牌的协议,并且看起来很满意.

  • @kosnkov我的帖子的简短版本是,如果你在数据库中保存访问令牌,你在每次请求API时都会访问数据库(在你的特定情况下这可能是也可能不是问题).如果保存刷新令牌并保持访问令牌"自包含",则只有在客户端决定刷新访问令牌时才会访问数据库. (25认同)
  • “尽管如此,我们仍然必须保留刷新令牌的数据库”-&gt; 不?我们可以只保留访问令牌的数据库,但只有在收到过期的访问令牌后才访问它!正确的?或者我错过了一些东西。 (3认同)
  • @RomannImankulov如果我理解它正确刷新令牌,我们可以保存到db并在我们想要撤销访问时删除它们,那么为什么不自己保存access tokens? (2认同)
  • 我个人不喜欢这样一种方法,即如果它将危及安全性(即使仅针对窗口的时间跨度),也无法通过数据库获得性能。一个人应该能够在必要时立即撤销一个access_token,因为几乎我们总是在处理敏感的用户信息(否则,我们很可能一开始就不会使用OAuth)。我不知道Facebook和Google这样的大公司会采用哪种方法。 (2认同)

cat*_*ave 431

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

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

话虽如此,因为对授权服务器和资源服务器的每次调用都是通过SSL完成的 - 包括原始客户端ID和秘密,当他们请求访问/刷新令牌时 - 我不确定访问令牌是如何"可妥协的"比长期刷新令牌和clientid/secret组合.

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

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

从上面引用,讨论刷新令牌的安全性目的:

刷新令牌...降低长期访问权限泄露的风险(在不安全的资源服务器,测试版或编码不良的资源服务器应用程序上的日志文件中查询参数,非https站点上的JS SDK客户端将access_token放入饼干等)

  • "刷新令牌,如果被破坏,则无用,因为除了刷新令牌之外,攻击者还需要客户端ID和机密才能获得访问令牌." 但客户端ID和密码也存储在设备中,不是吗?因此,有权访问设备的攻击者可以获取它们.那么为什么?在这里,https://github.com/auth0/lock/wiki/Using-a-Refresh-Token,写道,丢失刷新令牌意味着,他可以请求尽可能多的auth令牌,可能不在googles场景,但如果我实现自己的oauth2服务器怎么办? (44认同)
  • *"除了刷新令牌之外,攻击者还需要客户端ID和秘密才能获得访问令牌"*:那么使用刷新令牌和简单地辞职之间有什么区别? (34认同)
  • 刷新令牌可以由第三方使用,该第三方可以在不知道用户凭证的情况下更新访问令牌. (29认同)
  • @KevinWheeler不,客户端ID和机密是OAuth客户端的凭据,而不是用户的凭据.在谈论OAuth时,"客户端"通常是与授权或资源API服务器(例如,facebook auth提供者)接口的服务器(例如,stackoverflow web服务器).用户的凭据仅在用户和OAuth API服务器之间传递,并且永远不会为客户端所知.客户端密钥仅从客户端传递到OAuth API服务器,并且用户从不知道. (22认同)
  • Catchdave是对的,但我想我会补充说,自从他最初的回复以来,事情已经发生了变化.SSL的使用现在是可选的(当catchdave回答时,这可能仍然存在争议).例如,MAC令牌(当前正在开发中)提供使用私钥对请求进行签名的功能,因此不需要SSL.因此,刷新令牌变得非常重要,因为您希望拥有短期的mac令牌. (13认同)
  • @georaldc您需要通过2个挑战才能获得访问令牌.首先,您需要证明您是注册客户,通常通过指定您的客户ID和密码来实现.其次,您需要证明您有权代表他访问用户的资源.第二部分在auth代码流中以两种方式发生.首先,您可以让用户直接登录到auth提供程序,然后返回重定向URI的代码.随后您使用刷新令牌而不是auth代码,因此一旦原始访问令牌过期,用户就不必再次登录. (6认同)
  • 如果访问令牌被泄露,我们很可能会假设刷新令牌和其余凭据也被泄露,这整个过于不必要的复杂身份验证流程绝对毫无意义。 (3认同)
  • @MarekDec 我认为客户端 id+secret 和用户凭据是一回事吗?您是否需要 id+secret/user 凭据来获取新的访问令牌? (2认同)
  • @machineyearning 如果我的理解是对的,难道不知道身份验证服务器签署并发出新的有效访问令牌所需的全部共享秘密吗?如果客户端已经将它的共享秘密与刷新令牌一起发送,那么刷新令牌在该过程中扮演什么角色?除了我猜身份验证服务器知道它是否是过期令牌之外,刷新令牌中是否有任何数据在刷新步骤中变得有益? (2认同)
  • @machineyearning 我有点得到初始身份验证部分,涉及登录/凭据以检索访问和刷新令牌。所以刷新令牌只是作为您的凭据的两倍,实际上不再需要您的凭据,但仍然需要客户端 ID/机密?刷新步骤是否通常涉及处理状态?如果您实施了这样的选项,就像检查刷新令牌是否仍然有效/未被撤销一样? (2认同)
  • @georaldc是的,您可以将其视为对先前用户访问授权的引用,这意味着不仅要输入用户的凭据,还要具体说明他们授予您访问权限的资源.我已经看到刷新令牌与之前的一些元数据一起发布,例如TTL,如果那是你想知道的.但是,当您尝试使用过期,已撤销或无效的刷新令牌时,通常auth服务器必须提供相关的错误响应.请查看oauth2规范部分4.1"授权代码授权".就规格而言,它的可读性非常强 (2认同)

laa*_*uer 177

尽管上面有很多好的答案,我作为一名安全硕士学生和程序员,曾经在eBay工作过,当我看到买家保护和欺诈时,可以说分开访问令牌和刷新令牌在骚扰频繁用户名的用户之间有最佳平衡 /密码输入并保留手中的权限以撤消对潜在滥用服务的访问权限.

想想这样的场景.您发出访问令牌为3600秒的用户,并将令牌更新为一天.

  1. 用户是一个很好的用户,他在家里上网/下车你的网站购物和搜索他的iPhone.他的IP地址不会改变,服务器负载也很低.像每分钟3-5页请求.当他在访问令牌上的3600秒结束时,他需要一个带有刷新令牌的新的令牌.我们在服务器端检查他的活动历史和IP地址,认为他是一个人,并且表现得很好.我们授予他一个新的访问令牌以继续使用我们的服务.用户不需要再次输入用户名/密码,直到他达到刷新令牌本身的一天为止.

  2. 用户是粗心的用户.他住在美国纽约,他的病毒程序被关闭,并被波兰的一名黑客入侵.当黑客获得访问令牌并刷新令牌时,他会尝试模拟用户并使用我们的服务.但是在短期访问令牌到期后,当黑客试图刷新访问令牌时,我们在服务器上发现了用户行为历史记录中的一个显着的IP更改(嘿,这个人在美国登录,现在刷新访问波兰仅仅3600s后???).我们终止刷新过程,使刷新令牌本身无效并提示再次输入用户名/密码.

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

当我们尝试平衡我们的工作,用户体验和被盗令牌的潜在风险时,您可以看到刷新令牌已经完美地发挥了作用.您在服务器端的看门狗可以检查超过IP更改,api调用的频率,以确定用户是否应该是一个好用户.

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

  • 这些是一些很棒的政策和想法,但我没有在你的答案中看到任何本质上需要使用刷新令牌的内容.所有这些功能都可以仅使用访问令牌来实现. (57认同)
  • @Evert,同时使用访问令牌和刷新令牌的好处之一是访问令牌可能是短暂的,因此在不检查最初发布它们的服务器的情况下无条件地信任它们并没有太大的安全性.这可以允许您扩展基础架构,以便它的非关键部分可以信任存储在(签名)令牌中的信息,而无需直接访问用户的帐户信息. (12认同)
  • 我相信这个答案假定我们从不希望资源服务器自己进行高级访问控制(例如,检查针对各种数据库的IP活动等),而是他们只能依赖于完全隔离地验证访问令牌.虽然这种情况可能是显而易见的(出于性能原因),但鉴于其他帖子和评论中的混淆,对于每个人来说显然并不明显.这是一个很好的信息,但我觉得它错过了原始问题的重点.我建议至少明确上述假设. (9认同)
  • @Avi Cherry - 是的访问令牌可能是短暂的,如果仍然认为用户有效,它也可以刷新.不需要刷新令牌来执行此操作. (5认同)

B T*_*B T 70

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

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

  • 这很有趣,因为在Google的情况下,当您要求刷新令牌时,您还会通过客户端ID和客户端密钥发送.所以无论如何你每小时都要妥协. (14认同)
  • 由于标准[要求](https://tools.ietf.org/html/rfc6749#section-6)客户端凭证与刷新令牌一起发送,因此这个答案的前提是假的."因为刷新令牌通常是用于请求额外访问令牌的持久凭证......客户端必须通过授权服务器进行身份验证." 另请参阅@Rots的评论. (7认同)
  • A)我认为你混淆了客户机密和用户机密.永远不会从用户设备发送客户机密钥,仅从访问后端应用程序发送到提供后端应用程序的数据.B)允许公共客户端(无法保持客户端机密的客户端,如本机或javascript应用程序)的密码授权的oAuth服务器也将为该公共客户端提供刷新令牌授权,因此您不需要刷新令牌时发送客户端密钥.C)刷新令牌为后端提供"hart-beat"何时检查用户的有效性! (5认同)
  • "唯一目的" - 不洗.使访问令牌的TTL与想象的刷新令牌的TTL一样长. (2认同)
  • 由于 Andreas Lundgren 指出,这个答案是错误的 (2认同)

Adv*_*sus 49

为了消除一些困惑,您必须了解客户端密钥用户密码的角色,这些角色非常不同.

客户端是一个应用程序/网站/程序/ ...,由服务器来说,要支持验证一个用户通过使用第三方认证服务.客户端密钥是此客户端和身份验证服务器都知道的(随机)字符串.使用此秘密,客户端可以向身份验证服务器标识自己,接收授权以请求访问令牌.

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

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

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

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

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

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

  • 应用程序服务器不提供自行提供刷新令牌的方法,您不能要求它通过为其提供刷新令牌来生成新的身份验证令牌.它在需要时"在幕后"更新身份验证令牌. (6认同)
  • 请注意,您确实需要客户机密码才能获得刷新令牌.您可能正在考虑隐式身份验证流,您不需要保密,但在这种情况下不会发出或使用刷新令牌. (2认同)

小智 36

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


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

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

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

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

  • 这似乎与 OpenID Connect 和身份验证有关,所以我不知道这如何回答这个问题,即关于令牌刷新的动机。 (2认同)

Hon*_*ney 36

这个答案是在两位资深开发人员(John Brayton 和 David Jennes)的帮助下整理出来的。

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

让我们假设没有刷新键,让我们通过这个例子:

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

如果我是黑客并且拿到了你的钥匙,那么在 30 分钟结束时,我会把它寄给钥匙制造商并拿到一把新钥匙。无论钥匙如何变化,我都可以连续打开所有门。

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

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

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

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

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


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

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

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

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

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

分区有利于安全。

最后但并非最不重要的是看到这个很棒的答案


什么刷新令牌不是关于?

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

  • 为什么攻击者获取刷新令牌比获取访问令牌更难?使用 HTTPS 在传输过程中提供保护,但我需要将它们都存储在浏览器中,以防 SPA。所以攻击者可以同时攻击他们。我错过了什么吗? (13认同)
  • @Vmxes 从这个角度来看,我不认为它们有什么不同。但从浏览器、路由器、ISP、VPN 等之间的传输层的上下文来看,访问令牌每小时可以传递 1000 次,而刷新令牌仅传递一次。 (2认同)
  • 攻击者可以访问访问令牌和刷新令牌。关键是 - 通过长期访问令牌,受害者和攻击者都可以继续操作。但是,对于短期访问令牌和刷新令牌轮换,第二个刷新令牌使用两次,刷新令牌将停止运行,双方都会失去访问权限。 (2认同)

小智 18

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

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

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

  • "刷新令牌只允许客户重新认证..."是这里的一个重要方面. (2认同)

bit*_*der 11

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

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

  • 我不同意.访问令牌由auth服务器发出,以失效日期签名,并发送给客户端.当客户端将该令牌发送到资源服务器时,资源服务器不会联系auth服务器来验证令牌; 它只是查看(已签名和未被篡改)令牌中的到期日期.因此,无论您在auth服务器上做什么来尝试"撤销",资源服务器都不关心.有些人将客户端注销称为撤销(即客户端删除其令牌)但imho这是误导性的术语 - 我们想要"撤销"服务器上的令牌,而不是客户端 (8认同)

hey*_*ega 10

为什么不将access_token设为last_token,并且没有refresh_token?

除了其他人提供的很好的答案,还有另一个原因,为什么会使用刷新令牌和它与索赔.

每个令牌包含的声明可以包括来自用户名称,角色或创建声明的提供者的任何内容.随着令牌的刷新,这些声明会更新.

如果我们更频繁地刷新令牌,我们显然会对我们的身份服务施加更大的压力,但是我们正在获得更准确和最新的声明.

  • 将这样的"声明"放入访问令牌中是一种不寻常的不良做法.如[规范](https://tools.ietf.org/html/rfc6749#section-1.4)中所述,访问令牌"通常对客户端不透明".您是否有OAuth提供商的例子? (3认同)
  • @heymega当用户角色从ADMIN降级到REGULAR_USER时,期望用户角色需要立即撤销,而不是在access_token到期时撤销.因此,看起来在每个请求上访问数据库是不可避免的. (3认同)
  • @svlada 我想在这种情况下,将实体从 ADMIN 降级到 REGULAR_USER 的应用程序(在同一过程中)也需要撤销适当的令牌。即如果我们知道索赔会发生变化,我们不会等待到期,我们会立即撤销 (2认同)

Tạ *_* Tú 6

假设你制作了access_token最后一个很长的时间,而没有refresh_token,所以有一天,黑客得到了这个access_token,他可以访问所有受保护的资源!

但是如果你有refresh_token,它access_token的存活时间很短,所以黑客很难破解你的,access_token因为它会在短时间内失效。 Access_token只能通过不仅使用refresh_token而且使用client_id和来检索回来client_secret,而黑客没有。

  • “不仅使用refresh_token,还使用client_id和client_secret,这是黑客所没有的。” 1.假设它只是访问令牌,那么黑客还不需要client_id和client_secret吗?2.如果黑客是一名优秀的黑客,那么他也可以破解client_id和client_secret。不管那部分如何,黑客攻击其他东西对于比较来说并不重要,因为如果很难黑客攻击,那么在仅使用访问令牌的情况下也很难黑客攻击......长话短说,您不是在比较相同的情况。你正在混合它们 (2认同)