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

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

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

111816 次浏览

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

为了清楚地区分这两个令牌并避免混淆,下面是OAuth 2.0授权框架中给出的它们的函数:

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

现在,为了回答你的问题,为什么你仍然被发出一个刷新令牌,而不仅仅是保护一个访问令牌,互联网工程任务组在刷新令牌中提供的主要原因是:

出于安全原因,refresh_token只与授权服务器交换,而access_token与资源服务器交换。这降低了长期存在的access_token泄漏的风险,“一个访问令牌可以持续一小时,一个刷新令牌可以持续一年或直到被撤销”。Vs“访问令牌一直有效直到被撤销,而没有刷新令牌”;

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

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

博士TL; refresh_token不会增加安全性。它的目的是提高可伸缩性和性能。然后,access_token可以存储在一些快速的临时存储中(如内存)。它还允许授权和资源服务器分离。

“所以我不认为这比从一开始就给我一个访问令牌,而不打扰整个刷新令牌系统更安全。” 我也纠结于同样的问题。简短的回答是,刷新令牌是必要的,以确保凭据没有过期 下面的例子可能会有所帮助: 我有一个存储你医疗记录的数据库。你同意与你的配偶分享你的医疗记录。您的配偶使用他们的访问令牌从我的数据库读取您的记录。两周后,您的配偶再次检查您的医疗记录,并使用刷新令牌确保他们仍然拥有(来自身份验证服务器的)查看您的记录的权限。刷新令牌使您的配偶无需向身份验证服务器重新输入他们的凭据(用户名和密码),但它确实确保他们仍然具有访问资源的合法性。永不过期的访问令牌将不会知道您是否撤销了配偶访问您的医疗记录的权利

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

刷新令牌作为一种不惹恼用户的方法

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

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

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

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

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

另一方面,刷新令牌需要频繁地呈现给授权服务器,因此如果其中一个令牌被泄露,那么撤销或拒绝整个刷新令牌是很简单的,而不必更改任何签名密钥。

__abc0更常用,撤销能力不是很重要,因为它们的寿命很短。

__abc0使用频率较低,撤销的能力至关重要,因为它们可以用来生成新的__abc1。

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

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

因此,签名密钥可以作为__abc来提高性能。

Db存储的键可以作为__abc0使用,以便于撤销它们。

如果没有refresh_token,就很难找到一种提供低成本验证和简单撤销能力的机制。因此,由于性能原因,refresh_token存在。

使用短时间的访问令牌和长时间的刷新令牌至少有3个相关的原因。

不记名的令牌

从最初的问题:

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

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

如果访问令牌是短期的,则在一定程度上减轻了这种访问令牌的无限功能。

攻击面

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

同样,访问令牌的短寿命至少是某种程度上的缓解。

撤销

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

这种设置的缺点是不能撤销这样的令牌(不需要像撤销授权服务器的公钥那样激烈的操作)。

通过使访问令牌的生命周期很短,可以简单地允许它们运行完,而不是显式地撤销。

下面是来自OAuth 2.0文档的信息。

刷新令牌用于在当前访问令牌失效或到期时获得一个新的访问令牌,或获得具有相同或更窄范围的其他访问令牌(访问令牌的生命周期可能比资源所有者授权的权限更短)。

  +--------+                                           +---------------+
|        |--(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)授权服务器对客户端进行身份验证和验证 刷新令牌,如果有效,发出一个新的访问令牌(并且, (可选,一个新的刷新令牌)

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

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

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

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

只使用访问令牌比同时使用访问令牌刷新令牌风险大得多。

例如,你只使用访问令牌设置“100 days"截止日期,但有一天,访问令牌被黑客窃取。现在,黑客有有很大的机会自由使用访问令牌,最多100天用于不良目的

现在,你同时使用访问令牌集合“60 minutes"截止日期刷新令牌集合“100 days"截止日期,但是有一天,访问令牌被黑客窃取。现在,黑客有自由使用访问令牌60分钟的机会要小得多

现在,你会认为刷新令牌是否被盗。实际上,如果刷新令牌被黑客窃取,黑客仍然拥有有很大的机会免费使用刷新令牌,最多100天用于不良目的,但刷新令牌被窃取的概率远低于访问令牌被窃取,因为刷新令牌被使用每60分钟一次来刷新访问令牌(以获得一个新的访问令牌),而访问令牌被使用刷新令牌0,这要频繁得多。

所以,你最好同时使用访问令牌刷新令牌

这是一次很好的学习经历,了解了令牌、刷新令牌和缓存它。然而,(我很好奇,我在这里不给出任何建议)我们可以使用用户登录后返回的代码,当使用微软身份平台时。我们是否可以只存储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();
}
    

refresh_token模式使OAuth服务器处于控制状态,因此当发生时,如access_tokenrefresh_token泄露时,服务器可以进行干预。

如。

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