The wonder of JSON Web Tokens
JSON Web Tokens (JWT) is a way of statelessly handling user authentication. What does it mean? Well, JWT...
For further actions, you may consider blocking this person and/or reporting abuse
An alternative approach that I've experimented with (so caveats apply) is to keep a 'jwt version number' for each account (in db and/or memory). That is lightweight enough unless you have an enormous amount of users.
Though of course, the first thing to keep in mind is that JWT was simply not designed to work like/with/for this, so any solution we come up with will be a bit of a (conceptual) hack.
Totally agree :)
A simple "token blacklist" is not enough. It works for logouts, yes, but there are at least two other events in which you want to invalidate jwts:
For those you need to be able to blacklist users and user-date pairs. The user blacklist can be a simple check against the user database to see if the user exists and is active, the user-date can be a check against a date in the user record indicating the date at which Tokens become valid,and if the token's iat field is before that, it's invalid.
Of course, checking directly in every request is costly and defeats the purpose of jwts, so think carefully if you could just use an opaque token and check against a white list instead of a black list.
Thanks, Daniel!
The final solution, of course, depends on the app's needs :) But this was definitely a useful addition! Most likely one should handle all those cases in a fully functional app.
I came to a similar conclusion. If you really must have log out functionality, then you can use a black list. However, using a black list is not a lot different from the old school way of stateful sessions. You still have to lookup the token on every request to be sure it is still valid. So, the blacklist can have a performance impact to the service (or even a bottleneck) just like with session-based auth.
Using refresh tokens could help a little. With them you can implement short-lived auth tokens. For example, if the token expiration is 5 minutes, then you can be sure that a user's permission changes will take 5 mins at most to take effect. However, refresh tokens are considered insecure to keep in the browser, so no help for web apps. (You can do it using HttpOnly cookies, for example, but then getting a new auth token may be visible to the user with redirects.)
And taking refresh tokens to its logical extreme of getting an auth token before every API request... it is no different from looking up a blacklist or looking up an auth session by session identifier. It is still a lookup on every request.
The performance gains come by balancing expiration time with how responsive security changes must be. If security changes must be immediate, then the auth solution becomes stateful and more expensive to scale. No matter which approach you use.
Having refresh tokens is again, similar to saving a session. Yes, the traffic is vastly reduced since a refresh token is checked only when your JWT expires. But still, it doesn't provide any advantage over serialized sessions in terms of scalability. In the end, why have such a complex and potentially insecure architecture when you can simply use cookie + session-based authentication?
Tracking sessions and CSRF tokens across servers requires extra infrastructure (something like Redis) for scalability, which is far more expensive than using refresh tokens. The OAuth2 protocol is complicated yes. But since it is an open protocol, there are many libraries to help insulate your code from that complication. And you have to look at what it buys you. You can delegate the hard or tedious parts of security (authentication, password storage, forgot password functions, etc.) to a provider. You also avoid complication in your architecture by not depending on the uptime of the session tracking database and cost by not having to pay for its resource usage.
Great article! That's one of the reasons it's not recommended to use JWT for session.
See cryto.net/~joepie91/blog/2016/06/1...
Thanks. And yes, it is :)
But JWT has it's own invalidate() that you can use while logging the user out in the backend
You are right! It's just a lot of people decide to use JWT and then start wondering how to handle logouts :)
I also suggest thinking on what implementation suits the app best and choose JWT only when it's definitely the best matching solution.
I'm confused? If we add a blacklist from a db that we have to check, what is the purpose of using JWT at all? Isn't that one of the advantages of have JWT, that you don't need to check the db every time?
The answer is that JWTs are misused and often are the wrong tool for the job. Like any new thing, a lot of people jump on the bandwagon without analyzing how and why this works. I suggest this really good article for the ups and downs of JWTs and what are good use cases. It taught me loads about JWTs and also scaling in general.
Being logged in is a state. Being logged out is another state - with substates: missing login information and having the wrong login information. One token can only meaningfully represent two of those states: present and not present. You need another (stateful) medium to represent the third, if that is required. These are technology independant facts.
The good thing about blacklists is that they represent a FAR smaller state than the number of valid sessions, so you can probably keep those cached in memory. This is due to
So it's not that bad :)
Another solution could be,
"your secret"
+ the salt.It would make any existing JWT tokens invalid immediately without the need of a blacklist.
Thanks for posting this. I was looking to do the same with JWT.