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 conta
The following approach could give best of both worlds solution:
Let "immediate" mean "~1 minute".
Cases:
User attempts a successful login:
A. Add an "issue time" field to the token, and keep the expiry time as needed.
B. Store the hash of user's password's hash or create a new field say tokenhash in the user's table. Store the tokenhash in the generated token.
User accesses a url:
A. If the "issue time" is in the "immediate" range, process the token normally. Don't change the "issue time". Depending upon the duration of "immediate" this is the duration one is vulnerable in. But a short duration like a minute or two shouldn't be too risky. (This is a balance between performance and security). Three is no need to hit the db here.
B. If the token is not in the "immediate" range, check the tokenhash against the db. If its okay, update the "issue time" field. If not okay then don't process the request (Security is finally enforced).
User changes the tokenhash to secure the account. In the "immediate" future the account is secured.
We save the database lookups in the "immediate" range. This is most beneficial if there are a bursts of requests from the client in the "immediate" time duration.
------------------------Bit late for this answer but may be it will help to someone------------------------
From the Client Side, the easiest way is to remove the token from the storage of browser.
But, What if you want to destroy the token on the Node server -
The problem with JWT package is that it doesn't provide any method or way to destroy the token. You may use different methods with respect to JWT which are mentioned above. But here i go with the jwt-redis.
So in order to destroy the token on the serverside you may use jwt-redis package instead of JWT
This library (jwt-redis) completely repeats the entire functionality of the library jsonwebtoken, with one important addition. Jwt-redis allows you to store the token label in redis to verify validity. The absence of a token label in redis makes the token not valid. To destroy the token in jwt-redis, there is a destroy method
it works in this way :
1) Install jwt-redis from npm
2) To Create -
var redis = require('redis');
var JWTR = require('jwt-redis').default;
var redisClient = redis.createClient();
var jwtr = new JWTR(redisClient);
jwtr.sign(payload, secret)
.then((token)=>{
// your code
})
.catch((error)=>{
// error handling
});
3) To verify -
jwtr.verify(token, secret);
4) To Destroy -
jwtr.destroy(token)
Note : you can provide expiresIn during signin of token in the same as it is provided in JWT.
May be this will help to someone
You can have a "last_key_used" field on your DB on your user's document/record.
When the user logs in with user and pass, generate a new random string, store it in the last_key_used field, and add it to the payload when signing the token.
When the user logs in using the token, check the last_key_used in the DB to match the one in the token.
Then, when user does a logout for instance, or if you want to invalidate the token, simply change that "last_key_used" field to another random value and any subsequent checks will fail, hence forcing the user to log in with user and pass again.
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).
I just save token to users table, when user login I will update new token, and when auth equal to the user current jwt.
I think this is not the best solution but that work for me.
If "logout from all devices" option is acceptable (in most cases it is):
A db trip to get the user record in most cases is required anyway so this does not add much overhead to the validation process. Unlike maintaining a blacklist, where DB load is significant due to the necessity to use a join or a separate call, clean old records and so on.