ChatGPT解决这个技术问题 Extra ChatGPT

“刷新令牌”的目的是什么?

我有一个与 YouTube Live Streaming API 集成的程序。它在计时器上运行,因此我相对容易编程以每 50 分钟使用刷新令牌获取新的访问令牌。我的问题是,为什么?

当我通过 YouTube 进行身份验证时,它给了我一个刷新令牌。然后,我使用此刷新令牌大约每小时获取一次新的访问令牌。如果我有刷新令牌,我总是可以使用它来获取新的访问令牌,因为它永不过期。因此,我看不出这比从一开始就给我一个访问令牌而不是打扰整个刷新令牌系统更安全。

访问令牌是不记名令牌。这意味着不需要其他身份证明,只需访问令牌即可冒充您。因此,它们应该始终保持短暂的存在。另一方面,刷新令牌不是不记名令牌。当您向 YouTube 发送刷新令牌以获取新的访问令牌时,您还必须发送 client_id 和 client_secret。正因为如此,刷新令牌可以保持更长时间,因为刷新令牌和 client_secret 都不太可能被破坏。
@jmrah 为什么刷新令牌和 client_secret 被破坏的可能性较小?我假设所有令牌(包括访问令牌)都是通过 HTTPS 发送的,因此它们始终是加密的。
@OlleHärstedt,我猜不太可能以两种方式受到损害。首先,因为它们通过网络发送比访问令牌花费的时间要少得多——发起 MITM 攻击(或其他类型)的攻击者获得它们的机会更少。其次,如果攻击者要获得对服务器的某些访问权限,他们将需要获得 3 条信息(令牌、ID 和秘密),而不是仅获得一条(访问令牌),从理论上讲,这似乎更难做到。

C
Community

基本上,刷新令牌用于获取新的访问令牌。

为了清楚地区分这两个标记并避免混淆,The OAuth 2.0 Authorization Framework 中给出了它们的功能:

访问令牌由授权服务器在资源所有者的批准下颁发给第三方客户端。客户端使用访问令牌访问资源服务器托管的受保护资源。刷新令牌是用于获取访问令牌的凭据。刷新令牌由授权服务器下发给客户端,用于在当前访问令牌失效或过期时获取新的访问令牌,或者获取范围相同或更窄的额外访问令牌。

现在,要回答您为什么仍会获得刷新令牌而不是仅仅保护访问令牌的问题,Internet 工程任务组在 Refresh tokens 中提供的主要原因是:

出于安全原因,refresh_token 只与授权服务器交换,而 access_token 与资源服务器交换。这降低了长期 access_token 在“一个小时内有效的访问令牌,具有一年有效或直到撤销有效的刷新令牌”与“在没有刷新的情况下有效直到撤销的访问令牌”中泄漏的风险令牌。”

有关 OAuth 2.0 Flow 的更详细和完整的信息,请尝试阅读以下参考资料:

OAuth 2.0 流程:服务器端 Web 应用程序

Internet Engineering Task Force (IETF) 发布的 OAuth 2.0 授权框架

SO post - 为什么 OAuth v2 既有访问令牌又有刷新令牌?


刷新令牌也应该有助于获得新的刷新令牌吗?
为什么在过期时不获取新的短期访问令牌?如果您仍然需要向服务器请求新的 access_token,为什么还要拥有长寿命的 refresh_token?或者是真的,使用 refresh_token 我不需要维护有效的身份提供者 cookie,它会根据 refresh_token 发出新的 access_tokens,即使在 cookie 早已消失之后,如果用户想要获得一个,则必须输入他的凭据新的 access_token?
@JustAMartin 作为 OAuth2 客户端,如果没有刷新令牌,我需要再次启动整个授权流程(让用户“登录”并再次授予我权限),以便获得另一个访问令牌。刷新令牌绕过此要求,作为我作为客户已经收到用户请求访问令牌的许可的一种“证明”。
这个答案非常关注“什么”,而很少关注“为什么”。我认为一个真实的例子将使读者受益。
@Sammy Taylor 完全同意。我不敢相信我读了整面文字墙只是为了一无所获
C
Community

刷新令牌至少有两个用途。首先,刷新令牌是一种“证明”,表明 OAuth2 客户端已经从用户那里获得了访问其数据的权限,因此可以再次请求新的访问令牌,而无需用户完成整个 OAuth2 流程。其次,与长期存在的访问令牌相比,它有助于提高整个安全流程。我将更详细地讨论这两点。

刷新令牌作为不惹恼用户的手段

让我们用一个例子来谈谈第一个目的。假设您是一名用户,正在使用想要与您的 YouTube 帐户数据进行交互的第三方客户端 Web 应用程序。一旦您授予客户端应用程序使用您的 YouTube 数据的权限,您是否希望客户端应用程序在其 YouTube 令牌过期时再次提示您获得许可?如果 YouTube 令牌的到期时间非常短,例如 5 分钟,会发生什么情况。让客户端应用程序至少每 5 分钟提示一次您的许可会有点烦人! OAuth2 针对这个“问题”提出的解决方案是刷新令牌。通过使用刷新令牌,访问令牌可以保持短暂的状态(如果访问令牌以某种方式泄露或被盗,这是可取的),并且刷新令牌可以保持较长(更)寿命,允许客户端获得新的访问权限令牌过期而不需要用户的许可(再次)。

但为什么要刷新令牌?如果重点是不通过权限请求来干扰用户,那么为什么客户端不能简单地说“嘿,授权服务器,我想要另一个访问令牌。现在!”?或者,“嘿授权服务器,这是我过期的令牌,给我一个新的!”。好吧,刷新令牌用作一种“证明”,即客户端在某个原始时间点被用户授予访问权限。这个“证明”是由授权服务器数字签名的刷新令牌的形式。通过客户端提供刷新令牌,授权服务器可以验证客户端是否在过去的某个时间收到了用户的许可,并且客户端不必再次提示用户。

刷新令牌作为提高安全性的一种手段

然而,这就提出了一个问题,“好吧,如果刷新令牌被泄露或被盗,或者只是被恶意客户端应用程序保留而没有根据用户的请求删除它,会发生什么?攻击者不能继续使用刷新令牌无限期地(或直到它过期)获得有效的访问令牌?这个问题导致讨论我提到的第二个目的,即刷新令牌有助于更安全的流程。

访问令牌出现的问题是,一旦获得,它们只会呈现给资源服务器(例如 YouTube)。因此,如果访问令牌被盗或泄露,您如何告诉资源服务器不要信任该令牌?好吧,你真的不能。唯一的方法是更改授权服务器上的私有签名密钥(首先签署令牌的密钥)。我想这样做不方便,并且在某些情况下(如 Auth0)不支持。

另一方面,刷新令牌需要频繁地提交给授权服务器,因此如果一个被破坏,那么撤销或拒绝整个刷新令牌是微不足道的,而不必更改任何签名密钥。


意味着不惹恼用户为我解释了这一点。在我的上下文中,我从 Web 后端访问 API,因此我不必手动输入凭据,它们在应用程序中可用。我一直在想,为什么不每次都用我的凭据获取一个新令牌,为什么要存储一个刷新令牌并跟踪它的过期时间。我从没想过在手动输入凭据的用户工作流程中,这会非常烦人。
x
xmedeko

@Teyam 提到 SO 帖子为什么 OAuth v2 同时具有访问和刷新令牌?但我更喜欢那里的另一个答案:https://stackoverflow.com/a/12885823/254109

TL;DR refresh_token 不会带来更高的安全性。其目的是提高可扩展性和性能。然后,access_token 可能只存储在一些快速的临时存储(如内存)中。它也允许授权和资源服务器分离。


除了有安全原因,正如@Teyam 所述:“refresh_token 只与授权服务器交换,而 access_token 与资源服务器交换”
如果我们假设授权服务器作为资源服务器以某种方式得到更好的保护,这只会更安全。如果不是这种情况,它实际上就不那么安全了。如果刷新令牌被泄露,我可以使用它来获取新的访问令牌。
TL;博士??真的吗 ?
我喜欢对可扩展性的强调,我认为这经常被误解,我在这里总结一下:stackoverflow.com/a/71932878/8485567
A
Adam Cole

“所以我不认为这比从一开始就给我一个访问令牌而不用打扰整个刷新令牌系统更安全。”我在同一个问题上挣扎。简短的回答是刷新令牌是确保凭据没有过期所必需的。

一个例子可能会有所帮助:我有一个存储您的医疗记录的数据库。您同意与您的配偶分享您的医疗记录。您的配偶使用他们的访问令牌从我的数据库中读取您的记录。两周后,您的配偶再次检查您的医疗记录,并使用刷新令牌确保他们仍然有权(来自身份验证服务器)查看您的记录。刷新令牌绕过了您的配偶将其凭据(用户名和密码)重新输入到身份验证服务器的需要,但它确实确保了他们仍然具有访问资源的合法性。永不过期的访问令牌不会知道您是否撤销了配偶访问您的医疗记录的权利。


如果我撤销了配偶访问我的医疗记录的权利,即使它永不过期,访问令牌是否会无效?
访问令牌的寿命很短,通常在 30 到 60 分钟左右,并且极不可能有人向他们的数据(安全资源)授予客户端应用程序授权并在 30-60 分钟内撤销它。但是如果用户确实撤销了,那么授权服务器将撤销访问令牌和刷新令牌。此外,当接收者(在本例中为配偶)决定她/他不再需要访问受保护的资源时,一个好的客户端应用程序还应该自愿调用 /revoke 端点以放弃令牌。这样,当不再需要有效令牌时,它们就不会存在。
D
Dennis Meissel

以下是来自 OAuth 2.0 documentation 的信息。

Refresh tokens 用于在当前访问令牌失效或过期时获取新的 access token,或获取具有相同或更窄范围的额外访问令牌(访问令牌的生命周期可能比资源所有者授权的权限更短,权限也更少)。

  +--------+                                           +---------------+
  |        |--(A)------- Authorization Grant --------->|               |
  |        |                                           |               |
  |        |<-(B)----------- Access Token -------------|               |
  |        |               & Refresh Token             |               |
  |        |                                           |               |
  |        |                            +----------+   |               |
  |        |--(C)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(D)- Protected Resource --| Resource |   | Authorization |
  | Client |                            |  Server  |   |     Server    |
  |        |--(E)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(F)- Invalid Token Error -|          |   |               |
  |        |                            +----------+   |               |
  |        |                                           |               |
  |        |--(G)----------- Refresh Token ----------->|               |
  |        |                                           |               |
  |        |<-(H)----------- Access Token -------------|               |
  +--------+           & Optional Refresh Token        +---------------+

(A) 客户端通过与授权服务器进行身份验证并提供授权许可来请求访问令牌。

(B) 授权服务器对客户端进行身份验证并验证授权授予,如果有效,则颁发访问令牌和刷新令牌。

(C) 客户端通过提供访问令牌向资源服务器发出受保护的资源请求。

(D) 资源服务器验证访问令牌,如果有效,则为请求提供服务。

(E) 重复步骤 (C) 和 (D) 直到访问令牌过期。如果客户端知道访问令牌过期,则跳到步骤(G);否则,它会发出另一个受保护的资源请求。

(F) 由于访问令牌无效,资源服务器返回无效令牌错误。

(G) 客户端通过与授权服务器进行身份验证并提供刷新令牌来请求新的访问令牌。客户端身份验证要求基于客户端类型和授权服务器策略。

(H) 授权服务器对客户端进行身份验证并验证刷新令牌,如果有效,则发出新的访问令牌(以及,可选地,新的刷新令牌)。


我对最后一步有疑问。使用刷新令牌发送刷新令牌是不好的做法吗?我不应该那样做吗?
@VigneshS 我没有收到您的问题...如果您的会话即将到期,您可以发送刷新令牌以获取新的访问权限和刷新令牌。
L
Lahiru Chandima

access_token 更频繁地使用,并且撤销的能力不是很重要,因为它们是短暂的。

refresh_token 使用频率较低,撤销能力至关重要,因为它们可用于生成新的 access_token

验证签名令牌的成本较低,但撤销却很困难。

验证存储在数据库中的令牌成本高昂,但很容易撤销。

因此,签名密钥可用作 access_token 以提高性能。

Db 存储的密钥可用作 refresh_token,以便轻松撤销它们。

如果没有refresh_token,则很难找到一种提供低成本验证和易于撤销能力的机制。所以 refresh_token 由于性能原因而存在。


假设因为刷新令牌在请求中的使用频率较低,它们被拦截的可能性也较小,这是否也是正确的?
K
Klaas van Schelven

拥有短期访问令牌和长期刷新令牌至少有 3 个相关的原因。

不记名令牌

从原来的问题:

如果我有刷新令牌,我总是可以使用它来获取新的访问令牌,因为它永不过期。

尽管您可能总是能够使用刷新令牌获得新的访问令牌,但攻击者通常可能不会。这是因为您对刷新令牌的使用与您作为客户端的一些身份证明相结合,例如通过提供您的 client_secret。对于作为不记名令牌的访问令牌不需要这样的证明,即简单地呈现它们就足够了。

访问令牌是短暂的,这在一定程度上减轻了访问令牌的这种无限权力。

攻击面

访问令牌与(可能很多)资源服务器交换,这增加了泄漏的机会。刷新令牌只与授权服务器交换。

同样,访问令牌的短暂性至少是某种程度的缓解措施。

撤销

将访问令牌实现为签名的 JWT 是可能的(并且很常见)。在这种情况下,任何服务器(知道签名方的公钥,通常位于某个众所周知的位置)都可以独立验证访问令牌的正确性。这允许很好地解耦架构,因为资源服务器不必向授权服务器询问授权。

这种设置的缺点是不能撤销这样的令牌(没有像撤销授权服务器的公钥那样激烈的事情)。

通过使访问令牌的寿命很短,可以简单地允许它们用完而不是明确地撤销。


K
Kai - Kazuya Ito

仅使用 Access Token 比同时使用 Access Token 和 Refresh Token 风险更大。

例如,如果你只使用Access Token,然后将Access Token的长有效期设置为100天,那么最终Access Token被黑客窃取,黑客可以获得最多100天免费使用Access Token的大机会。不好的目的。

但是,如果您同时使用 Access Token 和 Refresh Token,然后将较短的有效期设置为 60 分钟为 Access Token,将较长的有效期设置为 100 天为 Refresh Token,那么最终 Access Token 被黑客窃取,黑客获得的机会要小得多。出于不良目的,最多可免费使用 60 分钟的访问令牌。

现在,你会想如果刷新令牌被盗。实际上,如果 Refresh Token 被黑客盗取,黑客仍然可以有很大的机会免费使用 Refresh Token 最多 100 天用于不良目的。但是Refresh Token被盗的概率远小于Access Token被盗的概率,因为Refresh Token每60分钟只使用一次来刷新Access Token(获取一个新的Access Token),而Access Token是每次访问资源的时候使用的,这很多更频繁。

因此,您最好同时使用访问令牌和刷新令牌。


T
Thisara_Welmilla

访问令牌的寿命很短。一旦过期,您需要一个新的访问令牌来访问受保护的资源。获得新访问令牌的一种方法再次验证资源所有者并获得授权授予然后获得访问令牌。但是,这会很烦人。

这个问题可以通过刷新令牌来解决。它的寿命很长。因此,您可以使用它来获取新的访问令牌,而无需与资源所有者交互。

好吧,你可能会想,拥有长寿命的令牌来获得另一个寿命短的密钥有什么意义。好吧,即使刷新令牌被泄露,攻击者也不能仅仅从中获取访问令牌。原因是攻击者需要客户端凭据以及刷新令牌。

因此,访问令牌将具有较短的生命周期(原因可在其他答案中找到)以提高安全性。为了避免资源所有者在访问令牌过期时烦人,OAuth 使用刷新令牌。


S
Salma

这是一次很好的学习体验,对令牌、刷新令牌和缓存有一些了解。但是,(我很好奇,我在这里不提供任何建议)在使用 Microsoft Identity 平台时,我们可以使用用户登录后返回的代码吗?我们是否可以只存储 CodeIdToken,并在需要时使用它来获取新的访问令牌?因为我在想我们用它来获取访问令牌,那么我们应该每次都使用它来重新生成访问令牌吗?

 ...
 ResponseType = OpenIdConnectResponseType.CodeIdToken,
...

private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
    {
        IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication();
        AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(new[] { "User.Read" }, context.Code)
          .ExecuteAsync();
    }
    

I
Inam Ul Huq

refresh_token 模式使 OAuth 服务器处于控制之中,因此服务器可以在发生诸如 access_tokenrefresh_token 泄露之类的不良情况时进行干预。

例如

如果 access_tokenrefresh_token 落入黑客手中,access_token 将很快过期,黑客可能会尝试刷新令牌,但服务器现在有能力/控制不再发出 access_token(考虑服务器得到了泄漏的信息)。