-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Public Client : Refresh Token Revocation on Token Reuse #1619
Comments
@mooreds This seems like quite critical functionality. Should it not at least have the |
I would always strongly suggest you do not manage refresh tokens on the client side. There are better ways to manage tokens. Doing everything on the client may be more convenient, but it is less secure and not a recommended way to utilize refresh tokens. |
It likely would not be practical to preserve all refresh tokens for all time when using one time use refresh tokens. A couple of ideas:
Perhaps there are other strategies as well w/out having to persist every refresh token even after it is no longer in use. |
I'm not sure I understand since the authorization code flow returns a id token, access token and a refresh token. Is your suggestion that only the backend of the client application manages the relationship to FA? I'm not sure how that works with the authorization flow since all of that happens with redirects on the client side. Traditionally the refresh token is kept on the client side to refresh the access token and keep the session alive. Even your site mentions this:
|
You could also add a well known claim into the token to indicate what the originating token was (first access token). Then all refreshes would would copy that forward and you only have to lookup the 1 token. Of course this only works if the refresh token(s) are JWTs or something where that can be encoded. |
The only thing that is guaranteed to be provided is the refresh token which is opaque. Claims in the We could make the RT a JWT, but that would increase the size. The RT is currently completely opaque and is just a random string essentially. This is useful because it has no meaning to anyone and does not identify the user, application, etc. |
Understood - by claim I meant a claim on your side with the opaque refresh token. How that is done / encoded into the token is up to you. Didn't mean it had to be a JWT - just that the refresh token would require some encoding mechanism to indicate the root parent. So your mechanism of using a portion of the token as a fixed component would work. |
I'm not sure if I'm missing something, but in the link you provided, all of the SPA related articles describe storing the refresh tokens in cookies, which are stored on the client. Does FusionAuth plan to address the attack vector/vulnerability, when storing and managing refresh tokens on the client? |
I don't believe we have any examples or recommendations to store refresh tokens client side unless in a secure HTTP only cookie. If you do find one, please let us know and we will correct it. If the refresh token is stored in an http only cookie, you cannot manage it client side.
This is something we'd like to solve. But I don't think this has anything to do with managing refresh tokens on the client. This should be avoided at all costs. Separately, if using a one time use refresh token, and a previously valid value in the sequence is attempted to be used, ideally we would add a policy to optionally invalidate the currently valid value as well. |
@robotdan I'm struggling to find examples of what you are referring to. Everything so far seems to indicate that the authorization code flow exchanges the code for a (id, access refresh) token set and that seems to be done in the SPA / Web Browser. Numerous articles are written about storing these in local storage, browser memory, etc. Can you please point me to how to do this better since you seem to indicate this is an anti-pattern. I want to make sure we are implementing security the right way. Notably, I'd want this for: Web Based SPA Also, we'd like to be able to access the system using a fingerprint/etc. on the mobile app. Today we are doing that with the refresh token being stored in the keychain and unlocking that with the fingerprint. If that isn't the right way to do it, please advise as well. None of this is relevant to this ticket, however. This ticket is about duplicate use of the refresh token and invaliding the entire refresh chain upon detecting this situation. |
A good illustration of the problem in the article An in-depth look at refresh tokens in the browser. Please implement! |
I think this is essential and has been implemented by Auth0 - essentially the scenario is that a one time use token is received by the client on refresh, which is not used by the client until the auth token expires. In between this time the refresh token has been used by an attacker to generate a new access code, and potentially a new refresh token. The client's auth token then expires and client uses the original refresh token, which will be rejected as invalid and the client will need to log in again. When the refresh token is used for the second time, it should trigger a revoke on all other refresh tokens for that application / tenant / user, otherwise they can continue to be used to regenerate further single use refresh tokens. A window in seconds for how long a previous token can remain valid after new refresh token generated would be useful so race conditions can be avoided. |
Refresh Token Revocation on Token Reuse
Problem
When using refresh tokens in a public client (mobile, spa) client authentication cannot be used to protect the /token endpoint. This means that the token can be "stolen" and used by a malicious actor. When this occurs, the application can be compromised by that attacker.
PKCE protects the /authorize endpoint, but that can't be used to exchange the refresh token. Since we are a public client, the refresh token is essentially a bearer token with no additional security.
This means that if a malicious actor gains access to the refresh token, they have an entry point to gaining access to the system with no additional layers of protection.
The suggested mitigation strategy is to use "one time" refresh tokens with short durations and to detect the attempt to use an already used token. When this is detected, all refresh tokens for that "chain" of refresh tokens should be revoked since the assumption is that the refresh token is compromised. This would close this particular attack. This combines the "refresh token rotation" suggestion with a detection of re-use of the token.
Today, Fusion Auth supports the rotation portion but not the revocation portion.
This allows the following attack:
Solution
When a one time token that was previously used to refresh the access token is used again, the entire chain of refresh tokens that have been minted from that re-used token must be invalidated so that the attacker cannot refresh their access token again.
Alternatives/workarounds
In the post in the forum, a discussion was raised about using web hooks to do this. Unfortunately, this won't work since the detection of the invalid JWT doesn't raise a web hook call. We'd need a "refresh token rejected" call to do this properly. Otherwise, we'd have to keep refresh tokens as re-usable and that opens other security issues.
Additional context
Original Post in Forum
Specification about Refresh Token Abuse Detection when Client Secret is not used
Detail of Attack/Mitigation (Auth0)
Detail of Attack/Mitigation (Ping Identity)
Detail of Attack/Mitigation (Log Rocket)
Add any other context or screenshots about the feature request here.
Related
Community guidelines
All issues filed in this repository must abide by the FusionAuth community guidelines.
How to vote
Please give us a thumbs up or thumbs down as a reaction to help us prioritize this feature. Feel free to comment if you have a particular need or comment on how this feature should work.
The text was updated successfully, but these errors were encountered: