Revoking or invalidating an authorization token?

Hi,

My apologies for crossposting. I wasn’t sure if the right place to ask this was here or on the Google Group.

I’m trying to figure out if Keycloak supports any sort of token revokation as described in RFC 7009, like with a /revoke API endpoint. I can’t seem to find it in the documentation. I see that there is a /logout API that can take a token (?), but I’m assuming that this would cause the user to have to log in again…

Here’s my use case - perhaps someone can help me understand if Keycloak supports this well.

  • A user is logged into my app, potentially on multiple devices (web, mobile, etc.)
  • The user makes a change to his subscription (e.g., he upgrades to a premium membership, or downgrades) while on one device
  • When he goes to the other device, where he is still logged in, his new membership is not reflected as it is only fetched by the app when an authorization token is obtained (the membership status would be in the JWT token) and as a result, he has the wrong level of access
  • If the user makes such a change on device A, I would like to be able to revoke or invalidate any tokens being used by device B to force it to get a new authorization token
  • I do not want this to result in the user having to log in again on device B, I just want them to get the new authorization (“silent” reauthentication would be fine as long as the user is not prompted for credentials, so if it is possible to invalidate just the authorization but not the authentication, that would be fine)

Is there a straightforward way to accomplish this? Can it be done with /logout somehow? Is it a better practice simply to use very short-lived authentication tokens to avoid this problem?

Thanks!

1 Like

Any news on this, @mlevin2?

“You can revoke the session (i.e., by invoking the end_session_endpoint), but not individual tokens. I doubt we’d add revocation for individual tokens as that would require much more state maintained on the server side.”

Ref:

Also see:

JWTs fundamentally lack the ability to reflect user data and claim changes in general, and that’s okay.

There is a general misconception, and many abuse JWTs. Tokens once issued shouldn’t be considered as state that can or should be changed.

A JWT is an authentication certificate primarily, that the holder uses so other parties can verify its actions. It should contain simple claims and carry authorization permissions, but in the event of user data, role, group, or permission change - an existing JWT token should not be updated. It can be invalidated though.

You either let the JWT token expire and thus invalidate, ensuring the client has to get the new token, now with the changes applied. This is actually the reason why JWTs should be short-lived.

Or you either use online validation. Offline validation is when your secured server validates tokens against a public key, while online requires the secured server to invoke your identity server to verify the token. If you have online validation in place, you can make use of Keycloak’s /openid-connect/revoke endpoint.

I suggest offline validation, as that’s what JWTs are meant for. With short expiration times, most use cases should be fine. If not, then your use case is way critical to rely on JWTs in the first place.

2 Likes

+1 for short expiration of the access token.

You can’t invalidate JWTs when using JWT decoders. All you can do is wait for it to expire (set low expiration time) or switch to introspection.

But none of the above is ideal and, anyway, it is now recommended that tokens are issued only to confidential clients (on the backend) and even that tokens do not leave the server at all. The recommended alternative is using an OAuth2 BFF, a middleware in charge of:

  • keeping session for the frontend
  • driving authorization code and refresh token flows
  • storing tokens in session
  • replacing the session cookie with the access token in session when forwarding a request from the frontend to a resource server

This is for instance what does the NextAuth library for Next.js. I also wrote an article on Baeldung to do that with Spring Cloud Gateway and the TokenRelay filter.

If tokens do not leave the server (like when using the BFF pattern), you keep a safe hand on it and can delete or replace it before it expire, immediately revoking or modifying user access.