> It is now recommended to have a refresh token with an expiration date, that can be long, and have that refresh token be single use. When it is sent to the authorization server to get a new access token, the authorization server will revoke the old refresh token and issue new refresh and access tokens.<p>I've been wondering briefly about this specific flow. It seems prone to a problem: if the refresh request gets <i>sent</i> successfully (and then invalidated), but <i>the reply is not received</i> 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?<p>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.<p>> 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.<p>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?<p>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).<p>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).
This is an ongoing struggle with providers like Azure AD. In our setup, we have function apps that are receiving OIDC tokens from our AAD provider - either from our tenant our others via B2B collab. In this arrangement, it is possible for a user to pass authn for up to 1 hour before revocation in the hosting tenant takes effect. You can reduce this expiration but it can make the experience really bad across the board for all apps.<p>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 <i>any</i> further access is effectively restricted.<p>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.
You're still stuck with a delay of you fetching the list of revoked tokens and someone getting to your service.<p>And that delay allows someone to come in with a compromised token.<p>However, with short expiration dates you achieve the same. You shorten the duration that a token is valid for.<p>Assume a token is revoked. It can be used against any target until they refresh their revocation list.<p>Same goes with just tokens with a short expiration date. It can be used against any target until it expires.<p>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.<p>Pick your poison.
Biscuit has been one of those pieces of tech that makes me re-think the way we organize our stack, with a couple of key ideas that make us more user-centric and enable decentralized systems.<p>Granted I haven't used it, on toy project or in anger, but it sounds really neat.
It depends on the scenario. I can think of the following, although they're pretty similar.<p>1. Lost/stolen access token.
2. Lost/stolen refresh token.
3. Disabled account.<p>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).<p>Revoking a refresh token would probably need to revoke all access (and perhaps identity) tokens associated with it.<p>Disabling an account would just need to revoke all tokens associated with it.
I'm not sure I understand the argument that expirations are inadequate: what's the likelihood of ending up with a token compromise without the client machine also being compromised? Further, if the client machine is compromised, isn't token revocation not much more than a fig leaf? If the machine is working correctly, and the user wants to explicitly terminate a session, why is erasing / forgetting the session secret not adequate?<p>I feel like I'm missing some critical, but non-obvious threat model here.
I'm still skeptical whether expiration times wouldn't be adequate for many applications, assuming these times are short enough, like five minutes?