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

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


当前回答

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

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

其他回答

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

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

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

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

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

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

Let's talk about the first purpose with an example. Suppose you, a User, were using a third party Client web application that wanted to interact with your YouTube account data. Once you grant permission to the Client application to use your YouTube data, would you want the Client app to prompt you for your permission again when its YouTube token expired? What happens if the YouTube token expiry time was something very low, like 5 minutes. It would get a little annoying having the Client application prompt you for your permission at least every 5 minutes! The solution that OAuth2 proposes to this 'problem' is refresh tokens. By using refresh tokens, the access token can remain short-lived (which is desirable in case the access token is leaked or stolen somehow), and the refresh token can remain long(er)-lived, allowing the Client to get a new access token when one expires without requiring the user's permission (again).

But why a refresh token? If the point is to not bug the User with permission requests, then why can't the Client simply say "Hey, Authorization Server, I want another access token. Now!"? Or, "Hey Authorization Server, here is my expired token, give me a new one!". Well, the refresh token serves as a kind of "proof" that the Client at some original point in time was granted access by a User. This "proof" is in the form of the refresh token being digitally signed by the Authorization Server. By the Client presenting a refresh token, the Authorization Server can verify that the Client received, at some point in the past, permission from the User, and the Client does not have to prompt the User again.

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

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

The issue that arises with access tokens is that, once acquired, they only ever get presented to the Resource Server (YouTube for example). So if an access token is stolen or compromised, how do you tell the Resource Server not to trust that token? Well, you can't really. The only way to do it would be to change the private signing key on the Authorization Server (the key that signed the token in the first place). I imagine this is inconvenient to do, and in some cases (like Auth0), is not supported.

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

“所以我不认为这比从一开始就给我一个访问令牌,而不打扰整个刷新令牌系统更安全。” 我也纠结于同样的问题。简单的回答是,刷新令牌对于确保凭证没有过期是必要的。

An example may help: I have a database that stores your medical records. You consent to sharing your medical records with your spouse. Your spouse uses their Access Token to read your records from my database. Two weeks from now your spouse checks again on your medical records and the refresh token is used to ensure they still have permission (from the authentication server) to view your records. The refresh token bypasses the need for your spouse to re-enter their credentials (username and password) to the authentication server, but it does ensure they still have legitimacy to access the resource. A never expiring Access Token would not know if you had revoked your spouse's rights to access your medical records.

access_token使用得更频繁,撤消的能力不是很重要,因为它们的生命周期很短。

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

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

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

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

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

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

这是一次很好的学习经历,了解了令牌、刷新令牌和缓存它。然而,(我很好奇,我在这里不给出任何建议)我们可以使用用户登录后返回的代码,当使用微软身份平台时。我们是否可以只存储CodeIdToken,并在需要时使用它来获取新的访问令牌?因为我在想,我们用它来获得访问令牌,那么我们应该每次都用来重新生成访问令牌吗?

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

and

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