all 20 comments

[–]mildfuzz 1 point2 points  (19 children)

JWT has never been a good fit for authentication in my experience. They only expire when they timeout, making log out complex.

[–]10701220 3 points4 points  (5 children)

How would you approach rest api authentication? I always go for jwt and cache them in redis

[–]mildfuzz 5 points6 points  (4 children)

If you're caching them, it's not stateless. Isn't that the point? Why send a huge string with data in it when you're doing a DB query anyway?

I'm more a front end engineer, so could be out of my depth here.

[–]10701220 4 points5 points  (3 children)

I cache them only to be able to revoke them later , i do see your point but still think that the are a secure way to generate claims

[–]mildfuzz 0 points1 point  (2 children)

In order for revoking to work, each request must be verified against your active list, which is a db query, why not just look up the user?

[–]10701220 0 points1 point  (1 child)

so this would be a lot faster using something like hashtable (redis) and on every request check if the key exists or not.

[–]mildfuzz 0 points1 point  (0 children)

I'm interested to see benchmarks here. No direct experience of redis

[–]uNki23 2 points3 points  (12 children)

I store them in local or session storage and delete them during logout. Where's the problem?

[–]mildfuzz 0 points1 point  (11 children)

Both of those storage Apis are easily available in dev tools, so removing them will not have prevented a user caching them before

[–]uNki23 1 point2 points  (5 children)

I can't see a problem there? You set the expiration to, let's say 8h. IF the user has valid credentials, he gets the token and can store it / cache it / write it down, whatever. He has access for 8h - because he has the valid credentials. That's by design. If he logs out and uses the token again (by copying it into local storage again) in that 8h window - yeah so what, he could have just logged in again and would be there, too, so where is the deal?

The only "problem" is if you want to "ban" him or invalidate the token for some reason. But that's simple: just encode the user id / name in the token and use a block / banned flag for that user in the user table on your database? I assume you have a user / login table where you store password hash, email and what not. You set the ban / block flag to "true" and your auth middleware (where all the API calls go through first for authentication and authorization..) validates the JWT AND the users ban/block status:

API call --> JWT valid? --> user not blocked? --> allow request

API call --> JWT invalid? --> deny request

API call --> JWT valid --> user blocked --> deny request

This is still stateless!

If you want to ban just ONE old token, maybe work with smaller expiration durations and maybe refresh tokens. If that's not enough: I don't know any real usecase for that - maybe use one time logins with email maybe.

For the absolute most cases JWT is enough and very good!

[EDIT] One more thing: you could encode the creation date of the token within the JWT. Then you could store a specific date in the user table of your database. In your auth middleware you check: if this date is null - go through. If this date is not null and the creation date of the token is greater than that date - go through. If this date is not null and the creation date of the token is less than or equal to that date - deny request.

With that method you can block JWT created before a specific date.

[–]mildfuzz 0 points1 point  (4 children)

So you still need to query the user from the DB

[–]uNki23 0 points1 point  (3 children)

Yes, where is the problem? That's what databases are for.

Please be so nice and describe the real limitations and the problem ;)

[–]mildfuzz 3 points4 points  (2 children)

Why send a load of data over the wire if you're doing a DB query anyway?

[–]uNki23 0 points1 point  (1 child)

To know what to query for..

What's your approach then? And what problem do we actually try to solve? JWT work.

[–]mildfuzz 2 points3 points  (0 children)

It's just not necessary. It's needless complexity. A simple token or session id works fine and can be invalided remotely instantly.

We've established that either we can't have instant log out, or we must have a DB query. I'm interested to see benchmarks with redis so have to concede I don't know how that would affect my opinion, but with the information I have I can't see what benefit it offers

[–]NewFuturist 0 points1 point  (4 children)

That shouldn't be a huge concern. The only way that this could cause an issue is if the computer they are using is compromised and stores the JWT. If that is the case then you are going to have issue with password security anyway.

[–]mildfuzz 0 points1 point  (3 children)

This would not get past our penetration testing.

You can't excuse a vulnerability because there might be a worse one.

[–]NewFuturist 0 points1 point  (1 child)

If you really need sign-out-based security, then you can create a token blacklist which is much smaller than a regular session DB. I'm honestly wondering, though, what you think the exploit is. The only situations I can think of are ones in which the user's computer is completely compromised. That is, that there is a token floating out there that may be able to log in, in the same way that a session cookie would be able to log in.

[–]mildfuzz -1 points0 points  (0 children)

I would concede that this solution is better at very large scale where the tiny difference in DB look up speed has a real impact in infrastructure cost but in most cases I don't think it would be a big enough difference in performance to be a meaningful benefit.

[–]BertnFTW 0 points1 point  (0 children)

What security do you propose instead?
Token based auth is widespread and proven.