Security implications of refresh token grace period

770 Views Asked by At

I have an OAuth2 server built with django-oauth-toolkit, and by default, refresh tokens are revoked immediately upon use. This means that if a client requests a new access token using a refresh token but doesn't receive the response due to a network interruption they will be forced to reauthenticate.

The library provides the setting REFRESH_TOKEN_GRACE_PERIOD_SECONDS which is an amount of time to wait between the use of a refresh token and its revocation. If a client uses a refresh token and does not receive the response, that original refresh token will still be valid for REFRESH_TOKEN_GRACE_PERIOD_SECONDS which allows the client to get a new access token without needing to reauthenticate.

As far as I can tell, the purpose of immediately revoking refresh tokens upon use is to prevent replay attacks, but since this authorization server exclusively uses https, it seems this is a sufficient defense against this type of attack.

Are there other vulnerabilities that can result from having a grace period for refresh token revocation? What would be the implications of never revoking a refresh token?

3

There are 3 best solutions below

0
On

I wrote an article about the problems this grace period is intended to solve: https://danmercer.net/p/refresh-token-false-positives

Like Kyle said in his answer, rotating refresh tokens enables the authorization server to detect stolen refresh tokens, because a token will be used twice. The AS can then revoke all tokens derived from that refresh token, which stops the thief at the cost of requiring the end user to grant access again.

Unfortunately, this "breach detection" can cause problems for legitimate clients, if a client tries to use a single refresh token multiple times. For example, this might happen due to a race condition (two threads in the client try to get a fresh access token at the same time) or a network error (the refresh token response fails to reach the client).

To help mitigate those problems while retaining most of the breach detection benefit, some authorization servers (including django-oauth-toolkit, apparently) apply a small "grace period" before revoking the used refresh token. This allows any concurrency or retries in the client to "settle" and get the new fresh tokens without triggering the breach detection.

Now to answer your main question: a small grace period does weaken the breach detection, but only somewhat. A malicious actor would have to guess when the true client is going to refresh the token. And even if they guess successfully, as long as you give both of them (the malicious actor and the true client) the same new tokens, then the malicious actor will have to make another lucky guess the next time the client refreshes its tokens.

Although this idea isn’t formalized in the spec yet, several authorization servers support some kind of grace period on refresh tokens, including Auth0, Okta, Fitbit, Slack, and Lucid. I’ve also found it in Fauna’s auth “blueprints” code.

1
On

Security considerations are mentioned in the RFC 7009 https://www.rfc-editor.org/rfc/rfc7009#section-5

You can have also an attack on TLS (HTTPS) if it's not configured/managed properly (insecure TLS versions, ciphers, man in the middle, expired cert, problems with Certification authority, ...).

You may have a problem with resource exhaustion on your server. Refresh token needs some resources - e.g. memory, DB record, ...

0
On

The description of the security benefit of token rotation in OAuth 2.0 Security Best Current Practice:

If a refresh token is compromised and subsequently used by both the attacker and the legitimate client, one of them will present an invalidated refresh token, which will inform the authorization server of the breach. The authorization server cannot determine which party submitted the invalid refresh token, but it will revoke the active refresh token. This stops the attack at the cost of forcing the legitimate client to obtain a fresh authorization grant.

Sounds to me like the intention of recycling is to guarantee the new tokens have exactly one recipient. A grace period, however short, would remove that guarantee. That said, token rotation with a grace period is better than no rotation as it would make it more difficult for an attacker to abuse a leaked refresh token without detection.

Since you are using TLS, another option could be to constrain the grace period to apply only to the current connection...