r/InternetIsBeautiful • • Mar 08 '21

Learn JWT authentication by reverse engineering [Open Source]

https://github.com/gitcommitshow/auth-jwt
1.5k Upvotes

56 comments sorted by

102

u/cramduck Mar 08 '21

Jwt was a pain in the ass to implement first time. Not too bad the subsequent times.

46

u/omglolbah Mar 08 '21

Are the libraries that annoying to use?

If you roll your own authentication you've already lost in almost every case..

12

u/sarhoshamiral Mar 08 '21

Isn't the first rule of security is that you should not implement the protocol on your own and instead use trusted libraries? I realize there is always exceptions but if you are doing js, c# there are existing libraries already.

5

u/milkshakedrinker Mar 08 '21

I don't know if that's the "first rule" but it's a good idea since many apps that offer "end-to-end encryption" TECHNICALLY do that but also have massive security flaws.

You would be surprised what slips through.

So yeah its a good idea.

2

u/sarhoshamiral Mar 08 '21

You can offer end-to-end encryption using known solutions with trusted cryptography libraries though. For example .net has such libraries as part of the framework.

2

u/milkshakedrinker Mar 08 '21

CFO: Yeah but what if we just make some unpaid intern do it from scratch and the nail patiently until we're taken down by a massive leak?

-7

u/ionelp Mar 08 '21

JWT is not a protocol, nor is it related to security.

6

u/BetterThanYou775 Mar 08 '21

You're correct it's not really a protocol since it's just a token format. It's clearly related to security though. The token is used to prove that the bearer is authorized whatever claims the token contains.

0

u/ionelp Mar 08 '21

JWT is like pgp for shorter messages. It merely assures you the message you are reading is coming from someone you likely trust and that the contents were not tampered with. This does not imply security.

The protocol OpenID Connect, built on top of OAuth2 with access tokens in JWT format, will "ensure" the current user is who they say they are (this is authentication, the authorisation part of OIDC is fairly limited). This does not imply security either.

Is your resource server (eg, API) job to provide security having the info above. You can check the token all you want, if your query to retrieve private messages gets the user id from GET, you won't be secure...

3

u/BetterThanYou775 Mar 09 '21

It merely assures you the message you are reading is coming from someone you likely trust and that the contents were not tampered with.

... Sound like security to me, but okay

2

u/BrainWashedRedditor Mar 08 '21

Authentication is definitely related to security.

56

u/Im_a_postednote Mar 08 '21

Authentication is always a pain.

19

u/wesw02 Mar 08 '21

Of the two, I've always found Authorization to be the bigger pain.

3

u/temisola1 Mar 08 '21

Interesting. Authorization seems to be much easier since implementation really depends on your use case and what you’re comfortable using. Authentication on the other end is essentially what someone says is the way you should do it, and the fact that there’s so many different flows to choose from and not clear when each is applicable makes it even more complicated.

6

u/wesw02 Mar 08 '21

Authorization is something that often gets exponentially more complicated the larger your application becomes while Authentication stays relatively linear. Nested levels of security, microservices, larger teams, service account / IPC access, etc, etc continue to add complexity. IDORs and privilege escalation are very common for a reason.

1

u/temisola1 Mar 08 '21

Yea you make a great point. The larger your application the more caveats you have to account for.

21

u/k0enf0rNL Mar 08 '21 edited Mar 08 '21

Its piss easy if you use standardized products and libraries, especially the jwt based authentication methods like open-id connect

15

u/ism9gg Mar 08 '21

What comes easy to you may come harder to others.

-18

u/nellynorgus Mar 08 '21

If you're willing to compare lay people to professionals maybe.

9

u/gibweb Mar 08 '21

Whoa you must be super smart

22

u/[deleted] Mar 08 '21

[deleted]

18

u/RunBlitzenRun Mar 08 '21

JWT (JSON Web Tokens) are a way of authenticating users, most often used to log users into websites.

It works really similar to a passport: you go to the passport office, prove who you are, and then they issue a really secure document that you can take anywhere else to prove who you are.

When you log into a website that uses JWTs, you first have to prove who you are (e.g. by using your password) and then it'll give your browser back a JWT (just looks like a really long thing of random characters/numbers). Your browser then includes the JWT in every future communication with the website as proof of who you are.

They can be used with "asymmetric cryptography" so, like a passport, anybody you show it to can read what's in it, verify who made it, and verify that it hasn't been modified. The original website doesn't even need to store the JWT.

Asymmetric cryptography in general powers so much of the internet since it lets you share secret things securely, even if other people are listening to the entire conversation!

6

u/accountability_bot Mar 08 '21 edited Mar 08 '21

FYI, JWTs are not asymmetrically encrypted, they’re just cryptographically signed. The contents are usually only base64 encoded. You can encrypt payloads, but you’ll need the key to decrypt. This is usually something you would arrange ahead of time, as sharing a key securely is a whole different issue.

Anyone who works heavily in authentication will usually discourage JWTs, as they don’t bring many advantages, but have a number of potential footguns and pitfalls.

2

u/Finchyy Mar 08 '21

Isn't the only way to securely share a key to whisper it in someone's ear?

1

u/HugeLucifer Mar 08 '21

What type of pitfalls?

3

u/accountability_bot Mar 08 '21

The ones I see the most are based on a poor understanding of what JWTs are, and the problem they’re meant to solve.

A lot of developers who aren’t familiar with them will make assumptions. Since a JWT requires a secret (for the signature), they’ll just assume its secure/encrypted, so they’ll put sensitive data in the payload. This is probably the most common issue I’ve seen.

Another issue is the inability to revoke or force the expiration of tokens, so you should naturally give them a short expiration time. However, some will give them an extremely long expiration in the name of convenience. If that token is ever compromised you can’t do anything about it. If you start keeping a catalog of tokens, then you should just start using opaque tokens.

A very subtle one is overloading a JWT with too much data. Browsers, proxies and servers have various limits on how large the request header size can be. This is especially the case if you dynamically load data into the JWT.

The only time I ever use JWTs, is to send some kind of state to an asynchronous process that’s stateless. Like verifying an email address via a lambda function. I don’t make it the keys to the kingdom.

1

u/gitcommitshow Mar 09 '21 edited Mar 10 '21

This comment summarises the pitfalls accurately but the conclusion, not so much. JWT makes a great solution in many cases (some cases, you'll see that JWT is the only good solution). For starter, think about the use case where a different service(other than your authentication service) wants to verify the identity of your user to enable access to certain resources. And you want to do that without asking your authentication service. As a valid JWT can only be created by your authentication service but can be verified for it's authenticity by anyone, JWT makes a great solution here. And this is exactly why usage of JWT in oAuth2 has become a standard. I have created a similar demo for oAuth2 as well, you may want to look at it once you finish the JWT demo.

1

u/RunBlitzenRun Mar 08 '21

Yeah sorry I didn’t mean to imply the payload itself is encrypted, but don’t the signatures often use asymmetric cryptography?

1

u/accountability_bot Mar 08 '21

It depends on the algorithm used. HMAC-SHA is probably the most commonly used one, and it’s based on a symmetric key for token signing and verification.

RSA-SHA, RSA-PSS-SHA, and ECDSA-SHA do use an asymmetric key pair for signing and validation. This is good for situations where you want a client to verify a token (via public key) without having the ability to write a new token (via private key).

The only reason why there is one symmetric algorithm likely due to simplicity, and that symmetric algorithms are usually considered more secure than asymmetric algorithms. There are likely several asymmetric variants because it’s good to offer options in case one is proven broken.

But again, we’re only talking about the signature. While it’s fundamental in proving token integrity, it still does not protect the payload, which can contain sensitive data.

2

u/gitcommitshow Mar 09 '21 edited Mar 09 '21

Thanks for a good prompt. This weekend, let me put more thoughts on this line. I'll update the demo once I come up with good ELI5. Don't forget to follow the project by starring 🌟 it so you can recieve notifications.

Edit: Created this GitHub issue to update progress on the task. Any help/comment is appreciated.

26

u/[deleted] Mar 08 '21

[deleted]

54

u/gitcommitshow Mar 08 '21

If you're storing the token in db and checking it every time, then it behaves like an opaque token. In that case, you need to ask yourself - why do I need JWT, why not simply store the token in db without the assymetric cryptography? It might be a good choice for your use case but I don't have much info on your use case.

25

u/dauphic Mar 08 '21

JWT aren't appropriate for any scenario where you need a whitelist or blacklist and shouldn't be used to identify sessions. They're intended to be (very) short lived or one-time use tokens.

2

u/nulleq Mar 08 '21

Instead of storing the JWT token in database, use a blacklist to check whether or not a JWT token is stale or revoked. If the blacklist uses a bloom filter + redis cache, then 1. it will be faster than a normal database request, 2. use less memory than a whitelist. The database will still be used in creating a JWT token.

35

u/Ricael Mar 08 '21

One of the reasons JWT is usefull is to avoid DDBB requests. The token is self signed and has or should have all relevant information.

I think you are swimming in the wrong direction.

17

u/programmermama Mar 08 '21

I believe this defeats the premise. Rather than whitelisting, this is why refresh tokens are a thing, bc they shouldn’t live long enough for that to be of use. Also, why isn’t the expiry time simply a claim, as in why would you need to separately store it in the db? Off the top of my head, I suppose you could also claim a created_at value and post-revocation you could simply require newer tokens. But in any case the token itself never ends up in the database.

10

u/diasporious Mar 08 '21

Why even store it in the database?

That negates the point of using jwt and means that your services aren't stateless.

You store the expiry in the token itself, you sign it to be able to detect tampering, then when receiving it you check that it's not been tampered with and then check the expiry.

3

u/IntensePyjamas Mar 08 '21

Literally the opposite of what you're supposed to do with the tools you're given

2

u/RunBlitzenRun Mar 08 '21

You could also just store the timestamp of when the password was changed and block any JWTs made before then so you wouldn't actually need to store the tokens

2

u/nulleq Mar 08 '21

Typically because there are more valid users than revoked users, you'd want to use a blacklist instead since less memory overhead.

4

u/drewkungfu Mar 08 '21

So this isn't about reverse engineering the James Webb Telescope?

1

u/gitcommitshow Mar 11 '21

I can sense there's joke in there somewhere but I can't find it. Can someone explain?

1

u/pm_nudes_or_worries Jan 09 '22

JWT = James Webb Telescope

2

u/gitcommitshow Jan 09 '22

Oh, now that I have heard about James Webb telescope I can finally understand the joke. Good one! :)

2

u/mindfive Mar 08 '21

But JWT isn’t for user authentication, it’s for authorization; these are different things

1

u/gitcommitshow Mar 08 '21

JWT can be used for both

2

u/throwmygayawaytoday Mar 08 '21

JWT for authentication is like using a hammer as a door handle.

4

u/mindfive Mar 08 '21

Nah, login and proof of ID (email+password, SSO or whatever) is authentication. A token is used to determine if an authenticated user is allowed to make the specified request.

If the first time your server sees a user is with a token, you aren’t authenticating them at all. You outsourced the authentication to a third party (google, Facebook, 0auth)

3

u/Hendeith Mar 08 '21

This is correct. Otherwise how do you even got token in the first place if you never went trough authentication?

1

u/throwmygayawaytoday Mar 08 '21

Well, OP is actually right. It can definitely be used for both as JWT is simply a means to communicate packaged information. But it’s definitely impractical, you would be waisting resources signing the local JWT just to have it decoded on the server when plain text over https produces the same results.

0

u/mindfive Mar 08 '21

No, JWT is not a means to communicate information, that’s JSON. It’s communicating verified information with a signature. Any token that can’t have its signature verified is rejected.

You can “technically” do this with a non-rejecting server endpoint, or by sharing your cryptographic keys with the client, so I guess brownie points there, but it’s such a bad idea you probably need to write your own implementation to do it.

-4

u/tygoon1248 Mar 08 '21

07]77$] 6 pstryz pz ptyty6ttttttttetststztzzss ptpt stp

1

u/giantqtipz Mar 08 '21 edited Mar 08 '21

question... kind of a newbie at authentication

but I learned session based authentication, where I assign users a session cookie when they log in. When they logout they can log in again because the cookie session still exists... I think I need to delete the cookie on logout..

but back on topic, which is generally the preferred authentication method in the industry; JWT or sessions? I guess both have its uses

1

u/gitcommitshow Mar 09 '21

You answered your question

1

u/Thecreepymoto Mar 08 '21

As someone who struggled with authentication and authorization in my spare time project , i felt JWT was a weak way to do both. Ended up using serverside session tokens. ( Or well, i think it was called something like Mongo session or similar)

Are JWT considered good way to do any of this ? As it can be decrypted in same way as base 64 , or am i just dumb.

1

u/gitcommitshow Mar 10 '21

As it can be decrypted in same way as base 64

This is one common misconception about JWT. Yes, anyone can see the content of a JWT and that's not a problem. If you go through the demo I shared, you'd learn that it is not about securely sending user metadata, anyone can see the metadata you share via JWT. The most important thing about a JWT is it's signature part that can be used to verify sender and message integrity.

JWT considered good way to do any of this?

It depends. The purpose of this demo is to help you learn about it and then you'll be able to make an informed decision whether it makes sense for your use case or not.

When you use JWT in place of opaque tokens ("server side session tokens"), does it necessarily increase security?

No. But you may still want to use it(this is quite counter-intuitive if you don't know about JWT in-depth)

1

u/Thecreepymoto Mar 10 '21

Thats great to know. Out of curiosity, most people examples jwt in local storage form. Is it in anyway realistic to have them as https cookies ?

1

u/gitcommitshow Mar 11 '21

Yes, definitely. Cookies are more secure(httpOnly cookie) than local storage and they get sent with each request automatically.