DEV Community

Cover image for Are you using JWTs for user sessions in the correct way?

Are you using JWTs for user sessions in the correct way?

SuperTokens on April 08, 2020

JSON Web Tokens (or JWTs) have become incredibly popular and you’ve likely heard of them before. What you may not have heard is that JWTs were orig...
Collapse
 
smortimerk profile image
Seán Kelleher

This is a nice overview, and I always find straightforward pros/cons lists useful. However, I would highly recommend against the practice of letting clients expect a non-opaque token for sessions; if you don’t, then you risk ending up in the scenario where it’s difficult to migrate to a new token type without breaking clients. I would instead suggest taking the OIDC approach where the session (access) token is opaque, but is paired with a non-opaque ID token. You can still use a JWT for the session token for scalability (to avoid DB lookups), but this allows you to decouple the session management from profile information which allows you to update your session management independently if necessary.

Following on from that, I think the following cons to using JWTs for session management are also worth mentioning:

Con: Clients need to implement state management for tokens: With JWTs and refresh tokens, clients need to have a mechanism for retrieving, storing, querying and refreshing the active token in a scalable (for their codebase) way. This mechanism is usually simple enough to implement, but can be tricky to integrate cleanly into a codebase (since it’s often a global dependency), and I’ve seen a number of projects suffer from subtle bugs from incorrect session management.

Con: Using fields correctly: From my understanding, a lot of the criticism of JWTs doesn’t necessarily come from their inherent insecurity, but the fact that they provide a lot of opportunity for misuse. In the case of the exported fields, there is twice as much opportunity for misuse, because not only does the client need to handle the fields correctly, but the server needs to implement them correctly. For example, are they issuing the correct audience value? Is the jti field unique? Is the sub unique, and immutable for that subject? This is ideally mitigated by using well-tested libraries, tools and services, but because of the perceived ease of use of JWTs it’s not uncommon for people to try and roll their own handling for them.

Collapse
 
supertokens profile image
SuperTokens

Hi Seán! Thank you for the detailed response!

It is recommended that the client should not have access to the access token (to avoid theft via XSS). This means that whatever the token type, it should not affect the client (even if the token type changes). Even when using OIDC tokens, one can still use JWT access tokens to get the scalability benefit. If using opaque access tokens, the API will have to query a db regardless of whether an OIDC token is being used.

Thank you for the two additional cons! Do you have any examples of codebases that have tried to implement the refresh token way, but did so incorrectly?

Collapse
 
smortimerk profile image
Seán Kelleher

Unfortunately not, these were usually in proprietary systems.

Thread Thread
 
supertokens profile image
SuperTokens

Alright, thank you either way.

If you get a chance to evaluate supertokens, we'd love to hear your thoughts and feedback. Would you consider using it for your app?

Collapse
 
totally_chase profile image
Phantz

These days most people already do use fresh/refresh pattern JWTs. Which is a good thing. I completely agree that long lived JWTs is a very bad idea. The whole part about JWT is supposed to cut down on database lookup time doesn't really work all the time either. I mean the JWT will probably return a user id upon decryption, don't you have to check if that's a correct user id through the db anyway?

Collapse
 
supertokens profile image
SuperTokens

You do not need to check if it's the correct user ID from the db since, if the signature checks out, then you can assume that it's the backend that created the JWT (since only the backend should have the JWT private key). In this case, we can be sure that the userId in the JWT was not tampered with since the signature is partly created based on this userId (implying that if the userId was changed on the frontend, the signature would not check out).

So if the signature checks out, we can be sure that the userId in the JWT is also something that your backend had set, which means it must be in the db.

That being said, if your JWT secret key is compromised, then the attacker can set the userId to any random string in which case all bets are off.

Collapse
 
nikosdev profile image
Nikos Kanakis

Solid explanation 👍

Collapse
 
supertokens profile image
SuperTokens

Thank you Nikos! Glad you liked it. Feel free to let us know if you have any questions

Collapse
 
fad16papa profile image
Francis

Nice article

Collapse
 
supertokens profile image
SuperTokens

Thank you Francis! Happy to answer any questions

Collapse
 
shaijut profile image
Shaiju T • Edited

Good 😄 , How can we securely store API key or token in the client side JavaScript Code , because anyone can see the JS code in browser.

Collapse
 
supertokens profile image
SuperTokens • Edited

Thanks Shaijut!

API keys are a different way to authenticate APIs. They have nothing to do with session management. The session tokens on the other hand, should be stored in httpOnly, secure cookies.