0

I'm trying to understand why having a JWT access token that doesn't expire is bad for my application. The way I have written my backend, when the JWT comes in, I verify it and extract the subject which is the user id. Then I look up this user in the database to get permissions/account status/etc. which I then use to determine whether or not the user has access to the data or action they are requesting.

I don't want the user to have to log in ever again after logging in once (in the same browser session). For example, on this site (stackexchange.com) I don't remember ever having to log in again in my current session.

Since I'm accessing the database for every relevant request, I feel like expiration time on JWT doesn't apply.

Where am I going wrong here?

2

Welcome to Security.SE. Let's take a step back and cover some higher-level topics first which will hopefully explain what you are looking for. The short answer is this: Long-lived tokens are dangerous.

Session Management

The standard session, getting a cookie with a token that is then stored in the database or caching server like Redis, is the way browsers handled keeping a user logged in, until recently. This cookie ideally would have no meaning other than being a token to information stored in the database, filesystems, or Redis. It acted as a key for lookup.

This property allowed applications to revoke sessions (e.g. "log out of all my devices") when needed. It also gives other properties, like identifying unique devices, but it rolls up in to that revocation.

JWT

I said until recently above, because with the advent of JWT, JSON Web Tokens, JWT usually acts as a stateless token. The server has no knowledge of that token other than what the token self-describes. This is also called an assertion. There are of course mitigations to keep people from asserting things such as signing the token. Assuming that is being done here, because most frameworks default to that now, it's less of an issue than what you can do with that token.

So what now?

In the interest of transparency: I cannot stand JWT. It is fraught with issues that are probably beyond the scope of this question, and I'm not aiming to derail. I tried to avoid bias in my answer, but in case anybody reading this sees a bias, that's why. :P

To answer the question now with some of this background: Should a token be stolen off a device (browser, mobile app, etc.), there's no normal method to revoke that JWT token. Because you kept it as a forever-token, even expiry of that token would not keep unintended audiences from accessing that account data. There's no server component, except for blacklisting that token, that can protect the user and the data stored.

To sum up: JWT's only real defense is expiry of the token. There's no revocation abilities that I'm aware of to protect the account. While long-lived sessions are a bad idea in general, it minimizes user friction. Who wants to log in every single time they come here? Sites like SE can revoke sessions on the server. You'll see this ability on Google and Facebook, for example.

  • So basically, the main concern here is that if a user's JWT is leaked then an attacker can impersonate the user and there is nothing the server can do to stop it at the authentication level. As a solution to this -- what if I had a db table that was just a list of revoked JWT ids (the jti field). I would add to this table whenever i have identified that a user's JWT has been compromised. Every request that needed auth would first check if the jti is in this table. – Infamous911 Oct 5 at 22:53
  • 1
    You could ... but that makes me really squeamish. Let's say you go back to the expiry being something like 30 days. You still lack the ability to revoke tokens should someone get hold of a token. So it's probably a good idea to add something if you wish to continue to use JWT. However ... a forever-token is generally a bad idea, and I would strongly discourage it. – h4ckNinja Oct 6 at 3:14
  • I guess I'm not really seeing the difference between JWT forever-token plus db blacklist of JTIs vs normal session-based auth where the session lasts forever (like on stackexchange). In both cases if someone gets the JWT/session cookie then they can impersonate the user until the JWT is manually blacklisted (in the first case) or the relevant session id is deleted from the session table in the db (in the second case). – Infamous911 Oct 6 at 3:24
  • 1
    Oh, don't get me wrong, I think the long-lived session on SE is a bad idea too. But that's a risk management call. I strongly discourage it, but given the scope of the question here, my only input other than JWT has additional considerations, is I don't like long-lived tokens, whether backed with a session management system, or with JWT. – h4ckNinja Oct 6 at 3:32
  • I feel that using really short lived (1 hour lifetime) JWT access tokens and long-lived non-JWT refresh tokens serves a good balance between user experience, revocability and scalability. Furthermore, changing refresh tokens on each use, can also allow you to detect token theft in a robust way (explained here). I hope this comment helps :) – Rishabh Poddar Nov 14 at 9:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.