Hacker News new | ask | show | jobs
by praveenweb 2315 days ago
JWTs have made client side auth integrations look better. But the problem is that common security considerations and implementation details are generally overlooked.

1. Tokens are typically stored in localStorage. (app becomes vulnerable to CSRF & XSS attacks).

2. Tokens can be stolen. Now this is generally controlled by having a very short expiration time.

3. Short expiration times mean persisting refresh tokens to do a silent refresh.

4. Blacklisting of tokens adds complexity and defeats the purpose of decentralising the auth workflow.

5. There's technically no logout. It's all done via very short expiration times. With multiple tabs open, logging out on one tab needs to be synced with rest of the tabs via some event listeners.

6. SSR rendered pages need to send along the latest refresh token cookie so that the browser can use it.

7. The refresh token is sent by the auth server to the client as an HttpOnly cookie to prevent XSS/CSRF.

My colleagues wrote a detailed guide which goes through these considerations - https://hasura.io/blog/best-practices-of-using-jwt-with-grap...

6 comments

That's a lot of work for a sessions replacement... http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-fo...
I think you're mistaken on point one, sites that use localStorage to store tokens are not in general susceptible to CSRF attacks [1]. The reason being that seperate domains can't access eachothers sessionStorage or localStorage in the browser. In fact that's one of the advantages of using the DOM storage APIs over sessions/cookies [2].

1. https://stackoverflow.com/a/35347022

2. https://youtu.be/WlmKwIe9z1Q?t=3658

> With multiple tabs open, logging out on one tab needs to be synced with rest of the tabs via some event listeners.

that's a problem with every site in general, which doesn't use any kind of event listeners.

Well, yes, but it's not exactly the same. Session-based logout (or JWTs with blacklisting) automatically protect resources that haven't been fetched yet, but leave open the possibility of lingering previously-fetched resources. JWTs without a blacklist even leave open the possibility of fetching additional resources with a supposedly logged-out credential. That seems like a much bigger hole.
For me blacklisting is bad idea in general. It can be achieved without blacklisting downsides by using asymmetric keys per user. Where you could rotate keys after things like logout or password change. Keys might be stored in replicated storage, same as session, and deleted/rotated as needed.

Don't get me wrong, JWT it's not silver bullet nor it was meant to be one in first place. It's not session replacement, but there are places where right implementation makes lot of sense.

1. you can still use a cookie if you really want to, or have it in your application state in memory for PWA, though a browser refresh will kill it.

2. Same for any authentication header or token

3. I'm not sure I see the problem

4. See 3, don't do it, use shorter lived tokens with a refresh if necessary.

5, see 4

6. Again, you could still use cookies, and longer lived, or state/revokation backed store... I don't do many SSR in practice, mostly PWA

7. That is absolutely an option... usually, I forward back with the token on the hash, then the first thing the app does is use the history api to pull it out and remove it from visibility... it does appear for a brief moment, but like anything else, you'd see it in devtools anyway.

> Yes! If a JWT is stolen, then the thief can can keep using the JWT.

Unless you have some form of fingerprinting the client who authenticated and received the JWT.

Sessions could be stolen too. The rest are essentially trade offs with the expiration mechanism. If your use case can't handle that, don't use JWT.
ergo: if it's ok to have an un-revocable insecure session - use JWT tokens.
Or use JWT + OpenID Connect in a centralized mode, as the article explains toward the end.