Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalidating JSON Web Tokens

For a new node.js project I'm working on, I'm thinking about switching over from a cookie based session approach (by this, I mean, storing an id to a key-value store containing user sessions in a user's browser) to a token-based session approach (no key-value store) using JSON Web Tokens (jwt).

The project is a game that utilizes socket.io - having a token-based session would be useful in such a scenario where there will be multiple communication channels in a single session (web and socket.io)

How would one provide token/session invalidation from the server using the jwt Approach?

I also wanted to understand what common (or uncommon) pitfalls/attacks I should look out for with this sort of paradigm. For example, if this paradigm is vulnerable to the same/different kinds of attacks as the session store/cookie-based approach.

So, say I have the following (adapted from this and this):

Session Store Login:

app.get('/login', function(request, response) {     var user = {username: request.body.username, password: request.body.password };     // Validate somehow     validate(user, function(isValid, profile) {         // Create session token         var token= createSessionToken();          // Add to a key-value database         KeyValueStore.add({token: {userid: profile.id, expiresInMinutes: 60}});          // The client should save this session token in a cookie         response.json({sessionToken: token});     }); } 

Token-Based Login:

var jwt = require('jsonwebtoken'); app.get('/login', function(request, response) {     var user = {username: request.body.username, password: request.body.password };     // Validate somehow     validate(user, function(isValid, profile) {         var token = jwt.sign(profile, 'My Super Secret', {expiresInMinutes: 60});         response.json({token: token});     }); } 

--

A logout (or invalidate) for the Session Store approach would require an update to the KeyValueStore database with the specified token.

It seems like such a mechanism would not exist in the token-based approach since the token itself would contain the info that would normally exist in the key-value store.

like image 759
funseiki Avatar asked Feb 24 '14 04:02

funseiki


People also ask

How do I invalidate JSON Web Tokens?

A common approach for invalidating tokens when a user changes their password is to sign the token with a hash of their password. Thus if the password changes, any previous tokens automatically fail to verify.

How do I invalidate access token?

To revoke an access token, specify type accesstoken. To revoke both the access and refresh tokens, specify type refreshtoken. When it sees type refreshtoken, Apigee assumes the token is a refresh token. If that refresh token is found, then it is revoked.

Should you use JSON Web Tokens?

Information Exchange: JWTs are a good way of securely transmitting information between parties because they can be signed, which means you can be sure that the senders are who they say they are. Additionally, the structure of a JWT allows you to verify that the content hasn't been tampered with.


2 Answers

I too have been researching this question, and while none of the ideas below are complete solutions, they might help others rule out ideas, or provide further ones.

1) Simply remove the token from the client

Obviously this does nothing for server side security, but it does stop an attacker by removing the token from existence (ie. they would have to have stolen the token prior to logout).

2) Create a token blocklist

You could store the invalid tokens until their initial expiry date, and compare them against incoming requests. This seems to negate the reason for going fully token based in the first place though, as you would need to touch the database for every request. The storage size would likely be lower though, as you would only need to store tokens that were between logout & expiry time (this is a gut feeling, and is definitely dependent on context).

3) Just keep token expiry times short and rotate them often

If you keep the token expiry times at short enough intervals, and have the running client keep track and request updates when necessary, number 1 would effectively work as a complete logout system. The problem with this method, is that it makes it impossible to keep the user logged in between closes of the client code (depending on how long you make the expiry interval).

Contingency Plans

If there ever was an emergency, or a user token was compromised, one thing you could do is allow the user to change an underlying user lookup ID with their login credentials. This would render all associated tokens invalid, as the associated user would no longer be able to be found.

I also wanted to note that it is a good idea to include the last login date with the token, so that you are able to enforce a relogin after some distant period of time.

In terms of similarities/differences with regards to attacks using tokens, this post addresses the question: https://github.com/dentarg/blog/blob/master/_posts/2014-01-07-angularjs-authentication-with-cookies-vs-token.markdown

like image 65
Matt Way Avatar answered Nov 25 '22 07:11

Matt Way


The ideas posted above are good, but a very simple and easy way to invalidate all the existing JWTs is simply to change the secret.

If your server creates the JWT, signs it with a secret (JWS) then sends it to the client, simply changing the secret will invalidating all existing tokens and require all users to gain a new token to authenticate as their old token suddenly becomes invalid according to the server.

It doesn't require any modifications to the actual token contents (or lookup ID).

Clearly this only works for an emergency case when you wanted all existing tokens to expire, for per token expiry one of the solutions above is required (such as short token expiry time or invalidating a stored key inside the token).

like image 34
Andy Avatar answered Nov 25 '22 07:11

Andy