Ask HN: Cookies vs. JWT vs. OAuth
I’m not very knowledgeable in security (that’s why I’m asking here), but will using JWT (with the token stored in the cookie) to keep the user logged in instead of sessions/cookies make my application more secure when the passport middleware executes req.isAuthenticated? I thiiink somewhere in that call it checks cookies or jwt, depending on implementation.
Also, I do not plan on opening the API to other sites, so OAuth is unnecessary. Is my understanding correct?
[+] [-] TheAceOfHearts|8 years ago|reply
You're correct in stating that implementing an OAuth provider is unnecessary.
I suggest reading the OWASP security guides. Start with Session Management Cheat Sheet [0], and after that Cross-Site Request Forgery (CSRF) [1].
Don't fear the cookies, all their gotchas are well documented and understood. There's lots of valid use-cases for stuff like JWT and OAuth, but I wouldn't bother with it at all until you're more comfortable with digging into the AuthN/AuthZ minefield. I'd consider understanding session management with cookies a precursor to trying to do anything fancier.
[0] https://www.owasp.org/index.php/Session_Management_Cheat_She...
[1] https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(...
[+] [-] gizzlon|8 years ago|reply
Cookies vs JWT makes no sense. You can put the JWT in a cookie if you want to.. apples and oranges.
[+] [-] dwaite|8 years ago|reply
Technology choices don't replace the need to understand that (although some choices may affect the urgency through unsafe defaults).
[+] [-] unknown|8 years ago|reply
[deleted]
[+] [-] welder|8 years ago|reply
[deleted]
[+] [-] modernpacifist|8 years ago|reply
Cookies: Highly compatible with most if not all browsers (and even headless tools). Lends themselves to having an expiry date and generally best when used with time sort of short-lived expiring session.
JWT: Everyone tends to use these in a stateless manner which means once issued, somewhat impossible to revoke without invalidating all JWTs or having a blacklist (and we're back at stateful). Plus some implementations had issues with downgrade attacks I think it was...
OAuth 1: Fine assuming you could keep clocks in sync and guarantee the secure storage of the keys/secrets. Good in that it didn't rely on HTTPS but if the secrets ever got compromised then the attacker would have free reign of that account until detected.
OAuth 2: Basically a complicated way to get short lived session tokens, potentially from a 3rd party API/auth source. Relies entirely on HTTPS to keep data secure in-transit and less of an issue if the session token gets compromised since its ideally short lived (because most want it to be stateless - those who keep a valid list of tokens sometimes skip the token expiry).
[+] [-] dwaite|8 years ago|reply
The flow becomes "redirect the user to have them authenticate, getting back a code. Make an API call to trade that code in for access. Once access expires, try to refresh it. If refreshing fails, send the user back to re-authenticate.".
The challenge people tend to hit is mistakenly trying to implement broad + reusable code at the start. OAuth 2 is described as a framework (e.g. optional parts and extensions leading to most likely non-interoperable implementations). Without a profile like OpenID Connect Basic Client, this includes a lot of extra work. Once you stop striving to implement generic interoperability in your client (or shoot for a limited profile like OpenID Connect Basic Client), the whole client implementation can fit in < 1 page of code.
[+] [-] tetraodonpuffer|8 years ago|reply
you can still do an oauth-like session + refresh token even with your own JWT implementation, just have a "refresh my session" endpoint that you go to with your refresh token (which is blacklistable), and have all the other calls be authenticated with the short-expiry stateless session token instead.
[+] [-] kevlened|8 years ago|reply
[+] [-] dwaite|8 years ago|reply
It doesn't do nearly as much good as one would hope knowing that a request came from a particular client if that request was possibly based on erroneous data, manipulated by a malicious third party.
[+] [-] mezzode|8 years ago|reply
[+] [-] amend|8 years ago|reply
[+] [-] cygned|8 years ago|reply
JWT is great until you get to the point where you want to have things like token revocation.
A simple session mechanism we use for our apps:
- Upon sign in, generate a session token, e.g. 32 characters. Session tokens are unique and fully random, not derived from any actual data
- In our scenario, a user can have multiple session at a time. We store two mappings in a Redis database; user-id=>user-object (for caching purposes, serialized JSON) and session-id=>user-id
- The second mapping has an expiration time which is the session length eventually, e.g. 30 minutes
- Upon every request, we take the session id from the request (header or cookie, cascadingly) and look for the session-id in Redis. If found, we prolong the time to live of that entry. From Redis, we got the user-id (because of the mapping) and thus we can retrieve the cached user object, too.
So we have a meaningless token (at least externally), our backend is still stateless (at least the application itself, Redis is stateful in nature) and we don't have to reinvent any wheels for automatically terminating sessions. In addition, it's easy to cancel session on demand and build a blacklist.
We wrote the handling ourselves (except for the crypto of course), because no express.js related library/middleware was flexible enough. And eventually we kind of trusted nobody.
[+] [-] Ninn|8 years ago|reply
What a flawed argument, there are techniques that allows for session revocation, even in an async stateless jwt context, i.e. By blacklisting, which will work great, and give you some nice properties, depending on your infrastructure and design.
Sadly, some appear to assume jwt is some special solution that does X right and y wrong.. but its really nothing other than a structured format in the end. But surely a lot of people do a lot of wrong stuff when deploying their stuff on top of jwt.
[+] [-] venantius|8 years ago|reply
[+] [-] merb|8 years ago|reply
Is basically the same thing than Login Form + Cookie, just that you return the Token instead of setting a Cookie.
So it's only more complex if you also act as a OAuth Provider, that implements all the other Flows.
[+] [-] unknown|8 years ago|reply
[deleted]
[+] [-] evfanknitram|8 years ago|reply
To me, saying Cookies vs JWT doesn't really make any sense. It's like asking what is more secure, JSON or MySql?
[+] [-] amend|8 years ago|reply
[+] [-] JepZ|8 years ago|reply
The differences between classic a session ID in a cookie vs. JWT is more or less, that JWTs often hold encrypted session information (stored on the client), while the session ID is just a random identifier and the session data is stored on some server (so its easier to build scaleable solutions with JWT). Security wise you might be interested, that cookies are sent automatically while JWTs are not (unless they are saved within a cookie).
You might wanna read: https://stackoverflow.com/questions/37582444/jwt-vs-cookies-...
[+] [-] kevlened|8 years ago|reply
[+] [-] clhodapp|8 years ago|reply
[+] [-] shiado|8 years ago|reply
[+] [-] sdfin|8 years ago|reply
I'd find it very helpful if somebody can recommend a resource, like some book, course or blog post that thoroughly explains the best practices and recommended strategies about authentication for APIs, websites and mobile apps in client/server and server/server communication.
[+] [-] eranation|8 years ago|reply
Cookies: a storage mechanism. If you use simple cookies (session GUID) for authentication, you must maintain state in some persistent storage to tell if a session ID is valid or not. httpOnly, secure cookies and CSRF protection are also required.
JWT: a digitally signed document containing claims about a user. Can be stored in a cookie or in localStorage or in your mobile app’s memory/temp storage. You can be stateless as the validity of the token is protected by its digital signature.
Oauth: a protocol for authorization. Can embed the authorization claims in a JWT token among other ways.
[+] [-] venantius|8 years ago|reply
Cookies - well known, hard to footgun yourself
JWT - new, complicated to implement, easy to footgun yourself
OAuth - generally only works in certain security models. You're probably still going to end up using cookies or JWTs as part of your OAuth state management anyways.
Personally, I use cookies for all "apps" and I'll use JWTs when I need authn/authz in a more complicated microservice architecture where the "clients" aren't browsers.
[+] [-] ukulele|8 years ago|reply
Maybe do some basic research first, then ask with more details on your setup and what is important vs not important.
[+] [-] amend|8 years ago|reply
[+] [-] nickjj|8 years ago|reply
I find with JWTs you end up dealing with cookies in the end, because on browsers you're definitely going to want to persist the token in a cookie so the user can have access in between requests.
Also, for the apps I develop, I often need to request the current user from a persisted database, so I'm doing a DB lookup on every request no matter what. Sure, I could cache this request in Redis but even on apps that have had to do this hundreds of thousands of times a month, it never caused any performance issues reading it directly from Postgres.
[+] [-] adamscybot|8 years ago|reply
[deleted]
[+] [-] snomad|8 years ago|reply
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-fo...
Also this previous HN thread https://news.ycombinator.com/item?id=13865459
[+] [-] hacknat|8 years ago|reply
[+] [-] imauld|8 years ago|reply
The issue with JWT revocation is if someone has a JWT that says they are an admin and then you make them not an admin or if an admin (or any for that matter) account is breached it's difficult to remove access from the attacker. With a session you just change the password and kill the session. This can be mitigated by short expiry times but a lot of damage can be done in a short amount of time by a determined attacker.
[+] [-] therealdrag0|8 years ago|reply
[+] [-] motohagiography|8 years ago|reply
[+] [-] dwaite|8 years ago|reply
1. You may decide you want to have multiple first-party clients to your API. Examples would be a web site, a native client, a command-line app. OAuth lets all of these different applications call the same API once they get a token.
2. There could be security value in segmenting the user authentication into an entirely separate app with its own database - it greatly reduces the attack surface which could be leveraged to get your user credentials to attacks against your user authentication (and likely registration) app, vs your entire website and all your APIs.
3. If you decide to open up your API in the future, you have already done a significant amount of the architectural legwork.
4. If you decide to support social logins (Facebook or Google for instance) in the future, you can do so just at your personal OAuth authorization service. Your apps don't care how they get an access token, and your APIs are still getting a local access token that they understand (rather than trying to understand Google or Facebook tokens).
[+] [-] jakelazaroff|8 years ago|reply
Here are some good blog posts that explain this better than I can (the flow chart in 3 is particularly illuminating):
[1] https://paragonie.com/blog/2017/03/jwt-json-web-tokens-is-ba...
[2] http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-fo...
[3] http://cryto.net/%7Ejoepie91/blog/2016/06/19/stop-using-jwt-...
[+] [-] Lazare|8 years ago|reply
Good. Sessions are the standard for a reason, and it's currently considered best practice. And if you've got a session ID, and your clients support cookies, then sure, use cookies for storing them.
> will using JWT (with the token stored in the cookie) to keep the user logged in instead of sessions/cookies make my application more secure
No. Probably less secure, although if you know what you're doing you can mitigate the issues. But certainly not more secure.
[+] [-] fimdomeio|8 years ago|reply
[0] https://stackoverflow.com/questions/31139365/can-you-use-coo...
We only stoped using cookies because of that since we wanted a more universal implementation so minimal changes had to be done between a web app and a mobile app implementation.
Other than that we would keep using session cookies.
[+] [-] runeb|8 years ago|reply
[0] https://developer.apple.com/library/content/documentation/Co...
[+] [-] nethsix|8 years ago|reply
Stateless JWT is useful in the scenario where one server is capable of authenticating a user (through password, social login, one-time password, etc.), and a different server holds resources that the user is trying to access.
The server doing the authentication will issue a stateless JWT with all the user credentials cryptographically signed, so that the user can pass the JWT to the server holding the resource to be granted access, assuming that server trusts the authentication server to perform authentication correctly.
Stateless JWT is useful here because the server holding the resources can verify the credentials of the user without contacting the authentication server.
Regarding OAuth, there are 2 sides to it. You can become an OAuth provider, which I reckon you are not interested to be. What you may be interested is to use OAuth to enable users of OAuth providers like Facebook, Twitter, .etc, to access your service, so that you minimize what you have to develop in terms of user management, i.e., you don't have to worry about user creation, email verification, password resets, etc., because all those have been performed by the OAuth providers.
I believe passport.js allows you to use OAuth to allow OAuth providers' users to access your service. passport.js may be a backend-base solution so you have to be somewhat familiar with OAuth to get started.
Alternatively take a look a https://oauth.io, which has a front-end based solution; I am not saying a front-end based solution is better, but rather it's easier to understand for someone starting out. Moreover they have JS fiddles that you can instantly play around with.
Check out the JS fiddle for creating a 'Login with Github' for your website here in just a couple of lines of Javascript: https://jsfiddle.net/dg9h7dse/1/
There is a full explanation of what the code is doing here: https://coderwall.com/p/sjbwcq/javascript-github-social-logi...
[+] [-] borplk|8 years ago|reply
Don't use other storage mechanisms for storing anything secret. Nothing beats cookies today.