shieldfy / API-Security-Checklist

Checklist of the most important security countermeasures when designing, testing, and releasing your API
MIT License
22.49k stars 2.6k forks source link

Don't recommend JWT #6

Open sethherr opened 7 years ago

sethherr commented 7 years ago

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 commented 7 years ago

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

sawmurai commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

Whats the alternative of JWT ?

tuupola commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

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.

Maikuolan commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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

bf4 commented 7 years ago

Matt- mind helping us help you by sharing what was unclear from the above? Also, any programmer that gives you 'the right way' should be ignored. Cryptographers and devs make some good arguments why JWT are often a poor data format, see above, yet it remains popular. Who is right?

B mobile phone

On Nov 18, 2017, at 2:42 PM, Matt Shull notifications@github.com wrote:

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 — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

itsMattShull commented 7 years ago

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 commented 7 years ago

Matt-

Sounds like that's a separate issue you should open.

I misunderstood your question. My answers:

Generally, using TLS/SSL helps.

If you're wondering why my answers don't mention JWT, that's why I suggested opening a new issue. You might also want to look at the OWASP top ten. https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project

You wrote:

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

On Tue, Nov 21, 2017 at 11:34 AM, Matt Shull notifications@github.com wrote:

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?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/shieldfy/API-Security-Checklist/issues/6#issuecomment-346102490, or mute the thread https://github.com/notifications/unsubscribe-auth/AAIuQvVx71c3WOcLUppBHF-lNyoyF4Muks5s4wmggaJpZM4OR6se .

warlockdn commented 6 years ago

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 commented 6 years ago

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.

https://github.com/shieldfy/API-Security-Checklist/issues/6#issuecomment-314627569

https://github.com/shieldfy/API-Security-Checklist/issues/6#issuecomment-316332544

etc

Agree that this issue should have some output

warlockdn commented 6 years ago

@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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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

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

bf4 commented 6 years ago

Disagree. He is an API builder. I build APIs. Cookies don’t work in certain situations, but that’s orthogonal to JWT. A cookie is a token in an http header. The point of the issue is, when you make a token, you almost certainly should not use the JWT spec to generate it.

Again, if you want to make a token, there’s a number of ways to make it. If you want to preserve state across requests, a cookie one place in the request/ response to put a session token. Someday I’ll write up my own research and experience. I point to Randall because I think he explains from a practical point of view, crypto aside, why JWT is a poor choice for authentication.

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)

brunocascio commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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:

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 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 commented 6 years ago

@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 commented 6 years ago

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

https://github.com/paragonie/paseto/issues/45

brunocascio commented 6 years ago

@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 commented 6 years ago

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 commented 6 years ago

@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 commented 6 years ago

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 commented 6 years ago

@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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

@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 commented 6 years ago

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

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 commented 6 years ago

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 commented 6 years ago

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:

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 commented 5 years ago

the way i use JWT--->

asevans48 commented 5 years ago

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 commented 5 years ago

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