23

I've read a lot about JWT and how to create "stateless" sessions through JWT. The gist of what I understand is that because of the signature & expiration, you can essentially send the entire session to be saved by the client and the server does not have to maintain a db to remember the session.

What I do not understand is what happens if your user needs to log out, or you need to invalidate a session before the expiration?

Technically, you could instruct the browser to delete it from the client side, but you can't be sure this actually occurred. The token itself is technically still valid and if your deletion instructions weren't followed, it could still be used.

Is this understanding correct? If so, isn't this a huge fault with client-side session management? Are there any methods to overcoming this aside from having the server store the session or making the expiration time short?

pedrofb
  • 37,271
  • 5
  • 94
  • 142
wlingke
  • 4,699
  • 4
  • 36
  • 52
  • 1
    To my understanding we should give every JWT an id and check if it is revoked in a blacklist. But since a blacklist is not stateless this may not be correct. I'm very interested in this topic, thanka for asking. – Hooch May 29 '16 at 08:46

3 Answers3

26

There are several reason to invalidate a JWT token before its expiration time: account deleted/blocked/suspended, password changed, permissions changed, user logged out by admin. So your question is on topic

There are several techniques to apply or combine depending on your use case

1) Remove the client token from local storage

2) Token blacklist: Store tokens that were between logout & expiry time, mark expired and check it in every request. Use a unique identifier jti or include last login date and issued at iat to remove old tokens

It is needed server storage. If you do not expect too many tokens to revoke, you also could use an in-memory blacklist. You only need to set an entry after updating critical data on user and currentTime - maxExpiryTime < lastLoginDate (iat)‌​. The entry can be discarded when currentTime - maxExpiryTime > lastModified (no more non-expired tokens sent). In this case is not needed to store the entire token. Just sub, iat and maybe jti

3) Expiry times short and rotate them. Issue a new access token every few request. Use refresh tokens to allow your application to obtain new access tokens without needing to re-authenticate and combine with sliding-sessions

Sliding-sessions are sessions that expire after a period of inactivity. When a user performs an action, a new access token is issued. If the user uses an expired access token, the session is considered inactive and a new access token is required. This new token can be obtained with a refresh token or requiring credentials

Other common techniques

  • Allow change user unique ID if account is compromised with a new user&password login

  • To invalidate tokens when user changes their password, sign the token with a hash of their password. If the password changes, any previous tokens automatically fail to verify. Extend this mechanism with other field of interest to sign. The downside is that it requires access to the database

  • Change signature algorithm to revoke all current tokens in major security issues

Take a look at Invalidating JSON Web Tokens

Community
  • 1
  • 1
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • Sign JWT with user's password makes whole authentication sort of.. stateful then, doesn't it? I mean, main gain of JWT is that any request may be authenticated by server without need to query dbo, which is huge performance gain. In this case server needs to query user's password when validating JWT. This is more or less the same as blacklist. – Luke1988 Apr 02 '18 at 11:46
  • @Luke1988 I would not qualify it as 'stateful' because the password is not part of the session, but as you indicate it will have a direct effect on performance. Assuming that revoking a token is an uncommon action, a blacklist is likely to be much more efficient – pedrofb Apr 02 '18 at 12:37
2

I've done some homework and seems that the better approach to implement the revocation is to use jti (id on Jtw) and a blacklist of revoked id (wich will be cleared when the token is expired). This make the JTW stateful for the only the blacklist part.

Hooch
  • 487
  • 3
  • 11
2

Blacklists are a JWT stateless violation. There is a lot of authentication schemes which you may use. JWT is based on stateless so it should be used that way. On the other hand, it is very common authentication scheme and if you have to implement it, and if you want your application (API) to be truly secure, some customisation must be allowed.

I personally use this two methods on my projects (separate or combined, depending on performance needs):

  1. Tokens Log. I do log every token issued in my project, with ID, claims, expiration and I do validate it on each request. If token is expired, it will be moved from this log to archive. Performance drop is not that awful.

  2. I also add to claims in addition to user's name a hash of user's secret (something like autogenerated hidden token or password) which is authorized in next step when loading user from dbo. This has no significant performance drop because the query for user is performed anyway. Drawback is that you may not invalidate concrete token, only all user's session.

Luke1988
  • 1,850
  • 2
  • 24
  • 42