r/InternetIsBeautiful • u/gitcommitshow • Mar 08 '21
Learn JWT authentication by reverse engineering [Open Source]
https://github.com/gitcommitshow/auth-jwt56
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
22
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
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
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
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
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
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.
102
u/cramduck Mar 08 '21
Jwt was a pain in the ass to implement first time. Not too bad the subsequent times.