Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't recommend JWT #6

Open
sethherr opened this issue Jul 9, 2017 · 47 comments
Open

Don't recommend JWT #6

sethherr opened this issue Jul 9, 2017 · 47 comments

Comments

@sethherr
Copy link

sethherr commented Jul 9, 2017

don't use JWT. JWT terrifies me, and it terrifies all the crypto engineers I know. As a security standard, it is a series of own-goals foreseeable even 10 years ago based on the history of crypto standard vulnerabilities. Almost every application I've seen that uses JWT would be better off with simple bearer tokens.

Also, link to a longer comment from him about why JWT is a bad plan.

@brunocascio
Copy link

brunocascio commented Jul 9, 2017

So, what do you recommend? I've seen subjective opinions and some nonsense as well.

@sawmurai
Copy link

sawmurai commented Jul 9, 2017

The only real problem I am aware off is that - if you adhere to the standard - the client can prevent/tamper with the encryption of tokens. That would indeed be a problem.

@nsteinmetz
Copy link

There are also macaroons but I don't have my own feedback yet on this

http://evancordell.com/2015/09/27/macaroons-101-contextual-confinement.html

@imerkle
Copy link

imerkle commented Jul 11, 2017

Whats the alternative of JWT ?

@tuupola
Copy link

tuupola commented Jul 11, 2017

Whats the alternative of JWT ?

Fernet is nice. Bad thing is the project seems to be pretty much dead. At least the maintainers have been in radio silence for a while.

@bf4
Copy link

bf4 commented Jul 12, 2017

JWT is just a way to make a token whose contents can be authenticated. If all you need is a token, JWT gives you nothing.

There's details around for generating a good token, in general. Assuming you've generated a token, the next question is how to use it: will you create an authorization token and refresh token like with oauth2? will you create a token and call it an 'api key' and just given it to the user? Will you require a 'client id', along with the 'client secret/api key'?

Also, if the authorization is for a web app, cookies make a good transport mechanism, especially if you set HTTP only and secure true.

Avoiding CORS is useful since it costs an OPTIONS preflight request. If we want to authenticate all requests on same domain, having an nginx proxy and avoiding CORS altogether makes the most sense (esp if we think of CORS as a way to improve upon JSONP) https://stackoverflow.com/questions/869001/how-to-serve-all-existing-static-files-directly-with-nginx-but-proxy-the-rest-t

see https://auth0.com/blog/2015/03/10/blacklist-json-web-token-api-keys/ https://stormpath.com/blog/build-secure-user-interfaces-using-jwts https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

In terms of security, all API calls should be using https and there is little difference in putting the token in headers or as part of the query string
set HTTPS only cookie

CSP, HSTS, CORS, WTF

@imerkle
Copy link

imerkle commented Jul 13, 2017

Here in what i came up with.

  1. I'm creating jwt encoding users id with a short ttl of 30 mins and creating a refresh token ( random token generated not jwt stored in redis )
  2. im passing the jwt token and refresh token back to client (or server requesting my api) and they save it.
  3. At each request they send me the jwt token via header authorization bearer and i authenticate the jwt to get the user id.
  4. if jwt is unauthenticated then i ask for refresh token and use it to verify id (stored in redis) and recreate the jwt and refresh token.
  5. Since after every 30 mins , jwt will expire its a mess to ask for refresh token and do extra round trip so im doing a periodic refresh of jwt after every 29 mins(or so) using refresh token stored in client.

What are the flaws in it ?

@hjr3
Copy link

hjr3 commented Jul 15, 2017

I agree that JWT should not be recommended. JWT (JSON Web Tokens) is a Bad Standard That Everyone Should Avoid does a good job of explaining the issues as well.

@Maikuolan
Copy link
Collaborator

Maikuolan commented Jul 19, 2017

@netcode Is there any final decision regarding JWT? Whether to accept/reject pull request #69 (currently open) could be influenced by any final decision regarding this issue.

Edit: Merged for now, seeing as the PR only adds links for information which already exists anyhow, and doesn't really change the context of the information already available.

@geeknik
Copy link

geeknik commented Jul 19, 2017

Stop Using JWT for Sessions
Stop Using JWT for Sessions Part 2: Why Your Solution Doesn't Work

Things to use instead of JWT

@netcode
Copy link
Member

netcode commented Jul 20, 2017

@Maikuolan , not yet , there is a debates all over the internet and inside our company too :D.

How about add a note regarding the issue raised here and the outside articles , what do you think guys ??

@Maikuolan
Copy link
Collaborator

I'd be in favour of that. With no clear consensus (and, depending whether one is in favour of JWT or against it, using it could be considered really good, or really bad advice), I think, adding a note to explain both sides of the argument, with appropriate links (pointing to some resources for how to use JWT, reasons to use it, reasons to avoid it, etc), would probably be the best solution for now.

@bf4
Copy link

bf4 commented Jul 24, 2017

@Maikuolan Following up my original comment and responding to subsequent ones, I think it would be beneficial to point out that from a security point of view, JWT can only authenticate data. It is, itself, orthogonal to authenticating a user session.

Let's consider the use case of an authentication token:

  1. It identifies an authenticated user

Let's consider the use case for a JWT:

  1. You want to encode information in the session
  2. You want to authenticate that information
  3. You DON'T need any session-specific information to respond to that request

Let's consider the number one misuse of JWT for authentication:

  1. You want to identify an authenticated user
  2. You encode the user_id in a JWT and return it as the session token
  3. A request comes in with the session token
  4. You decode the JWT session token and authenticate it
  5. You look up the user from the information in the session token

You'll notice that if we omit the steps with the word 'JWT' in it, you're just describing a session id as commonly used. You're still hitting a database or datastore to look up the user, but using extra CPU cycles to encode and decode the JWT, as well as more bandwidth, since it is bigger than a simple session id. Moreover, if you're serving data via SSL, authentication is less important. Moreover, if you're storing your session in a secure cookie, it's already encrypted, so encoding it has no additional benefit.

So, unless you have services that can answer a request solely based on the contents of the JWT, you're just wasting CPU cycles and bandwidth. This is especially relevant in CPU-bound applications such as Node.js.

What's really frustrating is that there's there this 'cookie vs JWT' debate. Which makes no sense because if you're using an HTTP header for authentication, please to remember that cookies are headers and JWT is a spec for encoding authenticated data. Unless you think it's reasonable to debate whether it is better to use 'Keys vs. Values' in hash/map or parameter.

@tuupola
Copy link

tuupola commented Jul 24, 2017

While we are at it, I would appreciate feedback on the Branca token spec which I have been working on as a secure alternative to JWT. Since it defines only token format and encryption scheme you can still use same payloads as with JWT.

nicolaiskogheim added a commit to nicolaiskogheim/go-kit-graphql-todo that referenced this issue Jul 25, 2017
Here is a link to an issue with more links to articles
explaining what's wrong with usin JWT on the client:
shieldfy/API-Security-Checklist#6
@Maikuolan
Copy link
Collaborator

Thanks @bf4 for the detailed reply and additional information, and thanks @tuupola for providing a possible alternative for us to look at. :-)

I think, one thing that could probably be safely agreed upon, regardless of which side of the fence people sit on in regards to JWT, is that thus far, there isn't a huge amount of context provided by the checklist at this point in terms of what we mean by "authentication". Maybe that would be a good starting point (e.g., providing some more context in the checklist for the types of authentication we're talking about, the context where such authentication should be used, what for, etc)?

@c4milo
Copy link

c4milo commented Aug 8, 2017

I don't see everything being wrong with JWT, there are some non recommended ways of using it. Recommend the safe ways of using it and stop spreading FUD.

@itsMattShull
Copy link

So here are my questions/scenarios if someone could clearly explain why JWT aren’t the right way and what is the right way:

  • how to do authentication for users of a website
  • how to do authorization for users of a website
  • how to do auth for a public API that developers can use to hit endpoints
  • how to do an internal API only used for the website

@bf4
Copy link

bf4 commented Nov 18, 2017 via email

@itsMattShull
Copy link

I don’t know that there is clarity above. I see a lot of disagreement so I wanted to know from the side of the “JWT is a bad pattern”, what’s the best way to do what i mentioned above.

If the answers are clearly laid out and I’m just missing it, could you help point me in the right direction?

@bf4
Copy link

bf4 commented Nov 21, 2017 via email

@warlockdn
Copy link

Its like everyone is saying don't use JWT but I can't see anyone explaining what else to use. Too much discussions on why it sucks but no one actually says what should be done. Tired of searching the whole web for answers now.

@bf4
Copy link

bf4 commented Mar 6, 2018

Its like everyone is saying don't use JWT but I can't see anyone explaining what else to use.
@warlockdn
use for what? it's just a token.

no one actually says what should be done.

#6 (comment)

#6 (comment)

etc

Agree that this issue should have some output

@warlockdn
Copy link

@bf4 I hope you understand my frustration. I saw the comments you mentioned and I have looked at it still its the same there are tonnes of stuff like tonnes of No's but only thing that I saw was use TLS yea well that works too. In web its still ok we can use csrf and session and use it. but how will someone implement it for a mobile app which only talks through api.

Any suggestions ?

@paragonie-scott
Copy link

Its like everyone is saying don't use JWT but I can't see anyone explaining what else to use

https://paragonie.com/blog/2018/03/paseto-platform-agnostic-security-tokens-is-secure-alternative-jose-standards-jwt-etc

@brunocascio
Copy link

Finally.. if you use jwt properly, does not matter.
If someone brokes your autentication even using the most secure standard, you and a lot of people will have troubles.
Keep out paranoia from here..

@bf4
Copy link

bf4 commented Mar 6, 2018

if you use jwt properly, does not matter.

@brunocascio

some would say that even when it has a good use case, of which there are not many, there are better specs to use.

https://speakerdeck.com/rdegges/jwts-suck-and-are-stupid https://www.youtube.com/watch?v=GdJ0wFi1Jyo cc @rdegges

@brunocascio
Copy link

brunocascio commented Mar 6, 2018

https://speakerdeck.com/rdegges/jwts-suck-and-are-stupid

Is about cookies vs JWTS. In APIs is not a valid scenario...

@bf4
Copy link

bf4 commented Mar 7, 2018 via email

@brunocascio
Copy link

brunocascio commented Mar 7, 2018

Did you know you can use secure http-only cookies over CORS from a static React site? Sounds like an API to me :) (though it’s better to avoid CORS if you can)

Yes, http-only flag should be used along with secure flag in order to prevent some known vulnerabilities like XSS or MiTM (at least), independent of the technology used in the frontend.
Cookies mean that the server persists sessions. Standard Rest APIS are stateless :)

The problem is finding a way to make an API stateless without cookies. JWT take place here...

Anyway, I like to debate it :) So, how to implement authentication if you can't use cookies?

@warlockdn
Copy link

warlockdn commented Mar 7, 2018

I guess we can just encrypt the sensitive data object too and add it to jwt token ? and whenever a request comes decrypt and use it. But would it be time consuming ?

Looked at Paseto but couldn't see a NodeJS library built on it i guess it was written in PHP

let's keep the conversation running its time we come to a solution.

Someday I’ll write up my own research and experience.
@bf4 do it soon if you could

@rdegges
Copy link

rdegges commented Mar 7, 2018

This is a really interesting topic. The talk linked to above is my talk which I'm always happy to discuss. It's quite hard to sum it all up into a short Github comment though.

The gist of it is this:

  • JWTs are larger than randomly generated API tokens because with JWTs you store data in them for stateless benefits which increases their size. Bigger size means more latency from the user to your API which means slower connections. And... If you aren't storing data in the JWT and are using it purely as a random string then you're negating any benefit they might have at all. Now they're just oversized string IDs.
  • JWTs, by design, are meant to be used to store cached data. That's their only use case in the entire world. And that is exactly what you don't want to do if you're building a secure web service: a website, API, IoT device, or anything in between. From the moment you decide to start caching authentication and authorization data in a client-side token you've opened yourself up to security issues because you're trusting that the data you receive is correct and valid. And... If you don't trust that data (or want to revoke tokens when needed) then you need to build some sort of centralized revocation list which again: negates any benefit you might have gotten from a JWT in the first place. This goes back to the original security vs. speed argument: it is truly impossible to have a secure anything if you're using cached data to validate your user.
  • Setting a short-lived JWT TTL is basically a shitty way of saying that "I want security and speed" but really accomplishes none of either: if you have a short-lived TTL you're still vulnerable to using invalid cached data and you most certainly won't be able to revoke tokens when needed (and if you can... then you are using centralization again and negating all JWT benefits).
  • Finally: if you realize JWTs are basically security anti-patterns but still want to use them you might think "OK: I'll just use a JWT but I'll only use it once and never rely on cached data." But if you do this then it goes back to argument 1 -- JWTs are simply less efficient API keys (or session IDs). They're accomplishing the same thing except with extra complexity/size over the wire which serves nobody any good and only complicates something simple.

In pretty much every single situation imaginable JWTs are worse than just using a randomly generated API key of some sort (or session ID if we're talking about web apps). There is no benefit to using them, only downsides.

Instead of using JWTs my recommendation is to keep it extremely simple:

  • If you're building a web app of some sort use server side sessions and store a cryptographically signed (and optionally encrypted) session ID as a randomly generated string on the client. Cache session data with invalidation in the backend if you want speed.
  • If you're building an API service of some sort generate random string API Key IDs and Secrets as key pairs for your users. Follow the same rules above: cache things server side if you want with invalidation for speed.

If security is a major concern: store API key secrets hashed using a fast algorithm (intended to allow for many concurrent lookups without hammering CPU/memory/cores with "good" algorithms like argon2, scrypt, and bcrypt). This way key secrets are unrecoverable (like what AWS does) and you can trust them slightly more.

@warlockdn
Copy link

@rdegges

If you're building a web app of some sort use server side sessions and store a cryptographically signed (and optionally encrypted) session ID as a randomly generated string on the client. Cache session data with invalidation in the backend if you want speed.

Yup this works for web app and is fine to an extent. adding csrf to it will slow down any attacker i suppose

If you're building an API service of some sort generate random string API Key IDs and Secrets as key pairs for your users. Follow the same rules above: cache things server side if you want with invalidation for speed.

But what about a mobile app where we still need to maintain sessions and we actually don't have access to cookies there. Can you suggest ?

@paragonie-scott
Copy link

Looked at Paseto but couldn't see a NodeJS library built on it i guess it was written in PHP

paragonie/paseto#45

@brunocascio
Copy link

brunocascio commented Mar 7, 2018

@paragonie-scott Just to clarify:

As you can see, with JWT, you get to specify an alg header. There are a lot of options to choose from (including none).

The approach of paseto is hiding the algorithm used to generate tokens?

There have been ways to exploit JWT libraries by replacing RS256 with HS256 and using the known public key as the HMAC-SHA256 key, thereby allowing arbitrary token forgery.

Could provide links about that? Would be useful in this thread!

About the other comments like encryption, revoking, data sent inside the token, etc. How paseto improves that?

@paragonie-scott
Copy link

paragonie-scott commented Mar 7, 2018

The approach of paseto is hiding the algorithm used to generate tokens?

It isn't "hiding" the algorithm. The algorithm is pre-negotiated and hard-coded for each "version". There is no ciphersuite agility, you get One True Ciphersuite for each version of the protocol.

Could provide links about that? Would be useful in this thread!

https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/

About the other comments like encryption, revoking, data sent inside the token, etc. How paseto improves that?

The facts about revocation and caching still apply to Paseto. It's meant to be a cryptographically secure alternative to JWT, but it still has the same use cases and pitfalls of JWT usage (albeit none of the vulnerabilities introduced at the joinery of cryptographic primitives).

@brunocascio
Copy link

@paragonie-scott I look like a JWT Fan 😆

https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/

Using kid property you can avoid RS256 -> HS256 vulnerability, I think.

By the way, I'll follow up your project waiting for nodejs implementations :).

@warlockdn
Copy link

I am not sure may be this is a silly question. How do you maintain session or validate a logged in user ?
If it was JWT then it was simple but since JWT shouldn't be used and is risky.

If it was a cookie based web app then it was fair and simple but I am talking about a service for mobile app.

Please suggest a way.

@bf4
Copy link

bf4 commented Mar 8, 2018

@warlockdn

How do you maintain session or validate a logged in user?
I am talking about a service for mobile app.

We're now off-topic, in my opinion, but let me ask you back: If you never heard of a JWT, would you be able to write an API for a mobile app? (Hint: the answer is yes, and is contained in all the discussions in this issues, and anywhere else people talk about authenticating. e.g. Do you have an AWS account? Can you access the API? You have a client id and secret right? Have you ever used oauth2? Or an auth token)

@warlockdn
Copy link

warlockdn commented Mar 8, 2018

may be I am missing something. Can you guide me to a resource, this auth thing is too confusing. I am aware of oauth but I don't have a requirement to use social networks for auth tokens. was looking at http bearer but still that method is like anyone with the bearer token can use it if anyone with some browser knowledge can just get it from the header

@tuupola
Copy link

tuupola commented Mar 9, 2018

It's quite hard to sum it all up into a short Github comment though.

I think it can be summed up in one sentence: one can achieve same things with both stateless tokens and plain old sessions. One should not use stateless tokens because plain old sessions already exist.

Although I do agree with most of @rdegges slides I do not agree with the conclusion that the stateless tokens are inherently bad. Note how I am not talking about JOSE / JWT but stateless tokens in general. I do agree JOSE / JWT is a cryptographically bad standard and after using it for a while I avoid it now myself too.

Stateless tokens are quite useful in m2m communication. My use case usually is to include the scope which the given token is allowed to access. Something similar as GitHub does.

it is truly impossible to have a secure anything if you're using cached data to validate your user.

I trust XChaCha20-Poly1305 tokens as much as I trust a randomly generated session id with data stored in tmpfs. Of course you can leak the token the same way you leak passwords and session ids. Whenever and however you credentials you will have problems anyway, no matter what tech you use.

Also I think it is bit misleading to say session sessions cookies have had "No vulnerabilities like... forever". Session hijacking has been around for a while. One could of course argue of course this is not a vulnerability in the cookie spec itself but how cookies are used.

TL;DR Everything is a compromise. Both plain old sessions are stateless tokens are ok. Most of the time you are good with plain old session. Neither of them are perfect. Avoid JWT though.

@paragonie-scott
Copy link

paragonie-scott commented Sep 20, 2018

@ShuhaoWang-AI:

Many people say JWT is not secure, the arguments are

  1. The claims are not encrypted
  2. If the private key leaks, anyone can fake a token
  3. If token leaks, you can not invalidate a token

I don't think these are valid arguments,

Because those aren't the arguments being made here, at all. Those are straw man arguments.

The real arguments are outlined here. Put shortly: JOSE (JWT, JWE, JWS, etc.) is an error-prone cryptographic design. The error-prone nature of its design has led to vulnerable implementations and avoidable cryptographic failures.

Nobody's arguing that "If the private key leaks, anyone can fake a token". That's just restating the premise of cryptography.

@paragonie-scott
Copy link

More on topic: Every PASETO implementation now supports v2.local. and v2.public. tokens.

  • v2.local. is XChaCha20-Poly1305
  • v2.public is Ed25519

Additionally, I've submitted the first RFC draft for XChaCha20-Poly1305 to the CFRG to review. If you're interested in symmetric-key authenticated encryption and might want to contribute to this RFC draft, check out the Github repository.

@Ocramius
Copy link

Lots of fud as usual: if the algo is locked, you are just doing fine (regarding OP).

PASETO is indeed a better specification, because the algorithm is indeed pre-defined, but it is a non-issue if you are using signed/encrypted tojens with pre-defined algorithms.

@Hinara
Copy link

Hinara commented Sep 30, 2018

The debate revolve around Stateful vs Stateless
JWT should be used as a stateless token. (Useless in statefull as you have session token for that)

Stateless

A stateless token allow you to easily decoupled parts of your application and split in into microservices.
For database accesses, the problem becomes how to split your application into microservices correctly, but this is not the question here.
Stateless token are not easily revocable! All of them! That's in the principle of stateless system.
If you want to make them revocable you need to maintain a list of revoked token (like it's done for TLS certificate and it's an horrible way to do so)

Stateful

Stateful tokens mean that you will have a SPOF (Single Point of Failure) as you will have session management as a center part of your system. I don't mean that it's a bad architecture, it can be enough for most cases (even more if you run a unique server), but in the case of scalability, it can be painful.
Session tokens are the mostly used type of stateful tokens .

Storing

For storing the problem is the same for JWT and Session token too, and for everything that you need to store on the client side ! So no it's not a good argument for or against JWT.

JWT

JWT content is not encrypted don't forget that!
The bad parts of JWT itself (in the stateless way) for me are:

  • Algorithm liberty (Library should allow you to choose which algorithm are allowed. Like for TLS servers)
  • You need to send the whole token (Send sometime useless data to the server)
  • May be bigger than some other stateless tokens

And that all!!

PS: In the case you just want to support only one algorithm for JWT.
Cut the header part when you send it to the client and add it back on the server side.

@diveinsky
Copy link

the way i use JWT--->

  • Select good JWT lib with all green checked, from jwt.io
  • Don't allow client to select algorithm for communication (if lib allows)
  • change JWT-secret occasionally
  • store the JWT-token as ENV
  • connect your horizontal servers via VPN and use this to update the JWT-token
  • add changing variable in JWT json, e.g. date_time
  • don't add any secret in JWT json
  • on top of JWT can use session based key management if needed, e.g for socketio

Will try PASETO too

@asevans48
Copy link

Aside from the above. If you really need more than information, why not include secure information in the additional information field via a fernet key. I use fernet all over the place. This could be used to encrypt scope and limit access in certain ways, pass encrypted data that is pretty hard to change; etc. while maintaining verifiable token scopes, issuer information; other verifiable things. A bearer token is nice for this though.

@kramik1
Copy link

kramik1 commented Jun 25, 2019

I am surprised I didn't see references to some RFCs in the discussion yet. I know their are a couple of drafts that don't recommend JWT using implicit or password grants particularly on SPA because the user environment (web browsers) is not constrained unlike a phone app. If you are using it within your own SPA without providing federated services (authorization codes to get access codes) they still recommend server side sessions.

https://tools.ietf.org/html/draft-ietf-oauth-security-topics-12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests