by geal on 7/4/23, 8:02 PM with 34 comments
by jcrites on 7/5/23, 3:27 AM
I've been wondering briefly about this specific flow. It seems prone to a problem: if the refresh request gets sent successfully (and then invalidated), but the reply is not received for any reason, then the authorization chain is broken. There's no way to get a new token. Is there a good 'standard' way to handle this problem?
On brief reflection, while writing this comment, it seems like the only solution is to fall back to some other (long-lived) identity (from which the original OAuth token was derived). But that can be an inconvenient fallback.
> The interesting property here is that if the authorization server sees the same refresh token twice, it means that the token was stolen: either the thief or the legitimate client already used the refresh token, and the other one is now requesting an access token too. In that case, the authorization server must revoke all current refresh and access tokens for this client.
That seems like an invalid conclusion to draw though. Multiple requests could simply be caused by failures (including race conditions). Should the refresh token really be single-use?
One alternative that I could imagine is that the refresh token can be used multiple times, but whenever it's used, then only the most-recently created tokens remain valid -- with all prior tokens (that were created from it) being invalidated. This would enable token refresh to survive failures, while also making any tampering evident (due to the appearance of unexpectedly invalidated tokens).
Edit: Another strategy might be to link together all access tokens into one "session": whenever a refresh token is used to create new tokens, those all count as the same "session" and the session is what's invalidated. (The 'session' would be established during the process issues the first tokens).
by bob1029 on 7/4/23, 11:45 PM
My current strategy for dealing with this is to add application-specific safeguards that re-verify the assigned roles of whatever user principal is present during more sensitive operations. If we detect that the user principal+token is no longer authorized, we can revoke our session bound to the AAD token and any further access is effectively restricted.
I've seen some other approaches, but I don't think you will get one that fits like a glove without making some alterations to the actual application which is consuming these tokens.
by WirelessGigabit on 7/4/23, 11:29 PM
And that delay allows someone to come in with a compromised token.
However, with short expiration dates you achieve the same. You shorten the duration that a token is valid for.
Assume a token is revoked. It can be used against any target until they refresh their revocation list.
Same goes with just tokens with a short expiration date. It can be used against any target until it expires.
I guess the difference is users extending their token lifetime more often (more load for your signing server) vs offering an API that you can use to share revoked tokens which needs to be checked every time (in which case it's no longer stateless) or checked every once in a while.
Pick your poison.
by FrenchyJiby on 7/4/23, 10:44 PM
Granted I haven't used it, on toy project or in anger, but it sounds really neat.
by dmatech on 7/5/23, 12:04 AM
1. Lost/stolen access token. 2. Lost/stolen refresh token. 3. Disabled account.
In the case of systems like Azure where access tokens have an "audience", they could theoretically send a revocation message to the audience endpoint (which would only need to care about revocations younger than the duration of access tokens, much like a CRL).
Revoking a refresh token would probably need to revoke all access (and perhaps identity) tokens associated with it.
Disabling an account would just need to revoke all tokens associated with it.
by ShroudedNight on 7/5/23, 12:04 AM
I feel like I'm missing some critical, but non-obvious threat model here.
by LanceH on 7/4/23, 11:47 PM
by grandpoobah on 7/4/23, 11:47 PM
by sverhagen on 7/4/23, 10:22 PM