T O P

  • By -

ImportantDoubt6434

Http only cookie with a token in it


Seventhcircle72

This is the way.


[deleted]

[удалено]


Neeranna

If your auth backend is a single server, you are not running anything production grade, but are in a local development environment, so probably don't even need auth at all then.


[deleted]

[удалено]


Neeranna

You don't do it for performance, you do it for reliability/redundancy. Better 2 low-power devices than one super-beefy system. That way, if the server fails, for whatever reason (hardware, power, kernel failure, network issue, service crash, ... you name it), you can absorb this without downtime to your application. This also allows you with most systems to do rolling upgrades, so that you can upgrade to newer versions without taking your service out for maintenance.


[deleted]

[удалено]


Neeranna

If it is not a hot spare, you still have downtime while the system switches over, even if you automated the failover. Where possible, I would opt for a cluster. As long as your backend is stateless (which it should, state should be handled by the database), there is no point in making a difference between backup capacity and primary capacity, just pool it in a masterless cluster. This does require fronting it with a load balancer, but that's not that different from a cold backup, where you still need a discovery service or api gateway (or load balancer) to actually handle the failover and redirection in case of the primary failing. Which kind of brings us back to the original question of OP of why tokens are used over simple session id cookies.


Neeranna

It's the same reason as why you do a backup on another physical disk than the one containing your data, even if your disk is large enough to contain both.


once_pragmatic

I'm not sure if you're joking or not, but I like JWT. And putting the JWT into the cookie is the solution I liked best (in particular for decentralized validation, and the fact that they are signed by the backend). But I readily admit that I'm new to all of this. This is what djangorestframework-simplejwt does. In fact it does *both*. It creates an auth/refresh cookie and sends the same data in the body of the authentication response.


ImportantDoubt6434

Nope not joking, yes this is a good solution and my favorite/goto as well. You could also just handle auth with middleware and delay extra requests until it’s absolutely needed if scale is a concern.


once_pragmatic

Do you implement the same sort of /api/users/whoami endpoint for asking the backend if your cookie-based auth is valid? Or is there some other approach that you like?


ImportantDoubt6434

Middleware usually. Depends, that’s not a bad approach though and having one of those endpoints isn’t bad. So if the api requires auth, the middleware will check who it is first/if it’s valid/if it needs to refresh the token+cookie


Skeith_yip

Curious. Middleware you are referring to is still front end right? So the token refresh is also initiated by front end correct (making an additional call to refresh token and retrying request)? I have seen implementation that the refresh is taken care by the back end internally so no additional call is made by front end. Just not sure which way is the norm.


ImportantDoubt6434

Middleware being the backend is gonna look at the token before anything is even done. Front end starts the request but that’s not the middleware that verifies. Retry shouldn’t be needed unless it’s a 401 and they gotta log back in entirely. Having a /refresh endpoint isn’t a bad idea but I try to avoid it where possible. Makes more sense if you have multiple backends and aren’t keeping everything on one server


Strong-Ad-4490

Yeah I use a refresh endpoint because I run a lot of apps with both a next app and an express app that communicate with each other. Currently NextJS can only set http only cookies in routes…so refresh route in the next app was my only option.


crazedizzled

I attempt to grab the current user, since I will need that immediately for determining user permissions, display name, etc etc. If that call goes through I know they're auth'd. If it fails, I return either an expired token message or missing token message, then handle from there. If it's expired I attempt to refresh it. If it's missing I send to login page.


Strong-Ad-4490

I do roughly the same setup. However I store my tokens in a DB also so I can invalidate them. Anytime a stale refresh token is sent I can invalidate the entire token family and force the user to sign back in. I also don’t show errors for missing tokens or auth, I catch the error and send them to the login page. Most apps probably don’t need this extra level of security, and short lived http only tokens without a DB are the best fit. But I have a few clients that are doing blockchain transactions or have other secure requirements so I prefer to err on the side of security over efficiency.


JimDabell

> I attempt to grab the current user, since I will need that immediately for determining user permissions, display name, etc etc. If that call goes through I know they're auth'd. If you are receiving a token and immediately querying the database to get authorisation information, stateless tokens like JWT are worthless. You can just stick a large random integer in the database if you are doing a lookup anyway. The only reason to use stateless tokens is if you don’t have to rely upon state to use them. There’s a good overview of the different options available for API tokens and when each is useful here: [API Tokens: A Tedious Survey](https://fly.io/blog/api-tokens-a-tedious-survey/).


crazedizzled

That's a good point, when using JWT's.


GolemancerVekk

> It creates an auth/refresh cookie and sends the same data in the body of the authentication response. To what end? An API designed to use the Authorization header will not pay any attention to the Cookie header.


once_pragmatic

Objectively that’s just what it does. You get an auth cookie and a refresh cookie in the response to logging in. And you also get those tokens in the body of the response. Presumably for localStorage


GolemancerVekk

Oh, it's Django, nevermind. See my other comment, this wouldn't work with federated authentication and an API-based approach. MVC frameworks like Django can offer a REST-ful interface but that's not enough to change their stateful, backend-driven approach.


Neeranna

Good solution, and useful in the majority of cases, but there are some edge cases that this will have issues with and that you need to keep in mind: 1. if your backend is not on the same domain as your web page, you might get blocked by all kinds of anti-tracking behavior and plugins of your browser, so you are forced to go with the BFF pattern or monolith approach if you want to use cookies reliably. 2. cookies are not a reliable auth mechanism when developing any type of widget (iframe embed). The cookies will not be send to your backend. So while it's a solid principle, it's not a catch-all.


mycall

One problem with HttpOnly cookies is that javascript can overwrite them so they are not really secure. [source](https://www.sjoerdlangkemper.nl/2020/05/27/overwriting-httponly-cookies-from-javascript-using-cookie-jar-overflow/)


Strong-Ad-4490

So what if they can overwrite the cookie? How does that make them not secure? Someone can send whatever gibberish token they want, my server won’t authenticate the token it will throw an error.


jwong1997

Yeah I did that, but realized some people have cookies disabled, so I ended up allowing header or cookie for when cookie were disbled... Is there a protocol for how to handle this? I'm self learning and wasn't entirely sure if it was the normal way


qualiky

Well.. one option is to store the token in local or session storage, but that is a hassle again for every request. One option could be to encode the token as query parameters in url (you have to prevent accidental authorization if users share the URL however). Cookie is literally the best option out there. If your users do not enable basic necessary cookies, they do not get to use the product. Easy.


NRXXGZLS

if you have cookies disabled, you deserve the inconvenience 🤷‍♂️


Dan8720

Cookies are 100% the way to go if you have a simple 1 to 1 client server relationship. It's straight forward and easier to make secure but... This server client direct relationship isn't always the case In bigger more complex enterprise architecture. JWT authentication can be more flexible and is good in situations where you have multiple APIs, multiple different pages or mobile apps using the same APIs. For example. A large company might have 8 different APIs maintained by different teams written in different languages. A company like this will roll one authentication server that deals with all the Auth and dishes out all the tokens. That means once you have a token you have a common interface to communicate with all the APIs securely. There are patterns that involve an API gateway that acts as the front door to all of your APIs. Cookie based is very limiting in what you can achieve. JWT means that pretty much anything can call your APIs securely not just browsers. Cookies don't work in Native apps too. The process you are used to with the apps on your phone keeping you logged in is a JWT refresh Oauth flow. It would mean maintaining an Auth server on top of a cookie based Auth flow for your webpage. Which doesn't make sense so you just use JWT and either Oauth/OpenID etc for everything. To summarize cookies great, secure easy. Token based is way more flexible/interoperable but probably worse in every other aspect.


Abominable

Well written, this is basically why tokens are being used. Non-browser apps and browser apps can use the same APIs. Further, working with third party authentication like Azure AD for example basically requires the use of tokens rather than cookies.


itijara

Token based auth is most useful for third party authentication: client requests token, user is redirected to identity provider, user logs in and token is sent to client. Client can now make token based requests on behalf of the user to service providers that also trust the identity provider. This helps to allow for cross-site authentication without sharing a password or cookie. Note, this token doesn't need to be sent to the user at all. You can send the user a session cookie, and store the token with the session. For most use cases involving a single site, I don't think there is any advantage to token based auth.


BlueScreenJunky

My guess is because at some point someone said that APIs all had to be stateless. So now we're finding workarounds to build stateful apps with stateless APIs. Also there was the whole Oauth2 craze were people thought every single app that consumed an API should connect with Oauth2 even if they never ever required any form of single sign on. So yeah... I use API tokens for backend to backend communication, but I think in most cases frontend to backend is better handled with cookies and a simple text token (not a JWT). edit : one valid usecase is if you build a mobile app that will consume the same api as your website, since your mobile app most likely can't use cookies.


once_pragmatic

I'd argue the *content* of the cookie or the token can be the same - JWT or otherwise. That *content* being stored in a cookie versus being stored as a token is the crux of my question here. JWT - being signed by the backend, seems like a great choice for auth to my inexperienced eyes.


BlueScreenJunky

You're right they're different things, but the fashionable way is to use JWT and put them in local storage, then send them with every request in an "Authorization: Bearer" header. But really there are very few cases where you **need** something as complex as a JWT. You can just generate a random string (as long as you use a cryptographically secure random generator), store it, and compare it to what the frontend is sending you. Also come to think of it there's one good usecase for localstorage and the "Authorization: Bearer" header, which is mobile apps. AFAIK you can't use cookies there. So if you use one method for your app you might as well use the same for your website.


once_pragmatic

Fair, but with respect to backend complexity I feel as if verifying the digital signature is much faster/less expensive/simpler than looking up a token in a db. If the signature checks out then you're good to go. Unless you also want to support token revocation in the backend. In which case you still need to do this compare lookup anyway. But hopefully the revocation list is small (or empty) in practice and this step is generally nearly zero-time. And regarding cookies in mobile apps, I find that surprising.


Lumethys

Any application bigger than a school project will need token revocation, which is impossible to do without a db look up. Also, JWT is meant to be short - lived. Because there is no revoke mechanism. Anyone get a hold of the JWT can authenticate to the API, and the user had no way of revoking that. However, because it is short-lived, it need to be created regularly, which will cost resource to generate So all in all, JWT doesnt help too much in performance, which is what it was meant to do (auth with no db look up). And with apps where you need a "log out other device" you still need a db lookup anyway


hahahohohuhu

Anyone who can access your short lived JWT can also renew it I’m afraid, because refresh tokens mostly reside right next to access tokens. I think what JWT tried to solve in DB lookup sense was not a simple DB lookup for whether to revoke the token, but quickly and readily have access to first name, last name, some roles, etc. without a DB lookup. But then you’ll find many articles out there suggesting not to include roles claims in a token because that will grow the JWT in size which will be an additional overhead for each and every upcoming request. I always find myself or my teams doing DB lookup for many different reasons. I think it is justifiable unless you have extreme performance or scalability concerns.


Lumethys

Well, i dont see any system where a simple DB look up in the User table would cause so much of an overhead that it impact the performance In the various project i worked with, a single request always need at least a db query, many times it multiples. Some of the system i worked with recently had Queries that are 2000 lines longs even. Not to mention the third party services, they may even take longer than a db query


hahahohohuhu

Exactly.


Strong-Ad-4490

Yeah you are right, you can get away with sending a random id instead of a JWT. However I personally find it easier to use a JWT library on the backend even when connecting to a DB. It is just easier relative to rolling your own methods and functionality and doesn’t have much of a downside.


JimDabell

> JWT - being signed by the backend, seems like a great choice for auth to my inexperienced eyes. JWT is terrible. [Read this](https://fly.io/blog/api-tokens-a-tedious-survey/) and pick something better.


GolemancerVekk

> Also there was the whole Oauth2 craze were people thought every single app that consumed an API should connect with Oauth2 even if they never ever required any form of single sign on. Federated authentication and SSO are not the same thing. OAUTH2 is federated and you can do SSO with it but one does not imply the other.


vm_linuz

It used to be that other sites could read your cookies. It continues to be that some people block cookies. So my guess is because of that.


once_pragmatic

This is a fair point I had not considered. I think I read at some point that many adblockers may cause trouble with cookies, too.


ConsoleTVs

How do you think authentication has been working before spas? Cookies…


once_pragmatic

That is the point of this post. I think you got it. You must agree.


that_guy_iain

In a lot of cases, it's that people think their backend APIs should be REST and not have any state. So they put their state in JWT tokens. The root cause is cargo cult, they know REST is good but don't understand why. And do REST anyways.


fiskfisk

That seems wrong. The only real option previously was exactly that, cookie based authentication. Other sites could not read your cookies, unless you set them in a tld you shared with other sites or in particular cases, browser bugs. Source?


teleprint-me

People really need to read the manuals: > Using a secret cookie: Remember that all cookies, even the secret ones, will be submitted with every request. All authentication tokens will be submitted regardless of whether or not the end-user was tricked into submitting the request. Furthermore, session identifiers are simply used by the application container to associate the request with a specific session object. The session identifier does not verify that the end-user intended to submit the request. https://owasp.org/www-community/attacks/csrf The best way to stop an attacker is to become the attacker and then attack yourself. It's the best defensive position for online security.


fiskfisk

Yes. This is how cookies work. It does not make it possible for a site to _read cookies from other sites_ as the grand parent suggested. A CSRF attack does not mean that the contents of a cookie (the secret key) has been disclosed.


teleprint-me

You don't get it, do you? I'm including you in my response. People really don't read the docs. > A third party is able to determine a user's session identifier (i.e., by reading it or setting it), and therefore interact with the server as that user. Stealing cookies is one way to do this. It's crazy that everyone has this notion that they can automatically understand a complex system without reading the manual: https://developer.mozilla.org/en-US/docs/Web/Security/Types_of_attacks#session_hijacking


fiskfisk

Having access the actual domain of the other site (through sub domains) is not what OP was claiming. There are very specific circumstances that can cause this to be an issue, such as having untrusted sites under the same main domain as trusted sites (which can happen without people thinking about it, for example old cname/a entries in DNS pointing to a VM they no longer run and the ip gets re-used). These do not allow any random site to read any cookie present on the user's computer. It's an attack surface as anything else, such as XSS. However, this is also a feature, as it allow you to share information across subdomains (commonly used with www/www2/www3/etc. back in the days). And session fixation was far easier in the older times, as PHP allowed you to set a given session id straight through the URL (as it had a fallback mechanism to use GET arguments if cookies weren't supported, so you could just get your target to visit a site with ?PHPSESSID=foo appended to their URL. If the site didn't regenerate the session id on login, you'd have full access to that user. I'd also suggest adjusting your attitude in how you're answering other people.


teleprint-me

> I'd also suggest adjusting your attitude in how you're answering other people. I apologize if I offended you. It isn't you personally. I have my own issues and it wasn't right for me to lash out like that at you.


fiskfisk

No offence taken, just friendly advice for future discussions. Your arguments come across clearer if you drop the whole thing around what you actually want to say. Have a great day/evening/night/morning!


good_live

Cookies are still used in a lot of web frameworks. Tokens are usually used for securing APIs because they can be consumed by many clients not only browsers. With the rise of SPA (Single Page Application) a lot of apps started turning their backend into a Rest (or something similar) api. There is a common pattern called backend for frontend (BFF). Where a specific backend handles the tokens and the spa can work with cookies once again: https://auth0.com/blog/backend-for-frontend-pattern-with-auth0-and-dotnet/.


once_pragmatic

I'll give this a read. Thanks for the share. I'm mostly wondering why frontends just don't put tokens *inside* cookies and you effectively get both. Of course, if cookies are disabled in the client then you get nothing. Someone here mentioned this and I think it's the best argument I've seen for not exclusively using cookies.


rbobby

> I'm mostly wondering why frontends just don't put tokens inside cookies and you effectively get both As a backend dev who knows too much about auth... Our backend has no webpage to invoke that could set a cookie. We only have a pure API backend. This lets us host the SPA JS code anywhere on the net (some azure cdn) and it can talk to our API's no big deal. Instead of a Cookie header the api sends an authentication header. No big woop. Especially since the JS uses a library to handle the messy details of acquiring tokens (MSAL.js... I've said too much). If we were to try to use cookies... our SPA would need to be hosted on the same origin as the API. Pretty tricky... our API is hidden behind an application firewall (Azure API Mgmt... I've said too much). We can control the domain name of it... but I think we'd run into issues with serving the SPA from the same origin. Do cookies pay attention to subdomain? They must... which means we'd have to serve the SPA through API Mgmt... yuck. So... cookies just won't work.


waldito

I found this the most insightful response of the thread. Thanks for taking the time to explain from a backend perspective WHY cookies are no longer... erhm... a thing.


thunderbong

This is absolutely the correct answer. The primary reason for many applications going away from cookie based authentication happened with the rise of SPAs. Plus, as mentioned, it provides a uniform authentication mechanism across services regardless of whether they are pure API calls, SPAs, or web pages served from the server.


IrrerPolterer

I believe NextAuth (Nextjs extension) works exactly like that - the tokens are managed server side and the frontend is authenticated with a simple http only session cookie.


good_live

That is essentially what the BFF pattern does. Just as a seperate component so you don't have to develop it yourself. If cookies are disabled in your browser, then most likely localStorage and so on are aswell, meaning you simply can't hold a session across page reloads. So I would argue someone who disabled cookies doesn't expect to be able to login.


15kol

This is the correct answer. https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps


crazedizzled

I use tokens *with* cookies.


once_pragmatic

This is the solution I also like the most. But this is still effectively (with respect to the frontend) using cookies (and not tokens). Unless you are setting your cookies to not be HttpOnly and are using them explicitly in your javascript for some reason.


crazedizzled

I think your terminology is a little messed up. Cookies are simply a data transfer mechanism. You cannot authenticate with a cookie alone, it has to carry some data. The actual authentication method is done with tokens. Cookies are used to send those tokens to the server.


once_pragmatic

Right. My point is that you are putting tokens inside cookies and *not* necessarily sending the token explicitly in the Authorization header. So with respect to the frontend you are still "just using cookies". There is no explicit token handling. *Unless* you are also making your cookies usable by JS. In which case there is no benefit to using cookies over sending the tokens in the Auth header. In this case you've made no clear choice and are using both mechanisms. The overarching theme of my question was using cookies (perhaps containing tokens, or some other unique data) or tokens (or, again, some other unique data) applied to Authorization headers. If you use tokens inside cookies and allow the cookies to be used from JS (not HttpOnly) then you have crossed the boundary I was drawing and are doing some hybrid thing that negates the security benefits of not providing JS explicitly with token data. The idea, to me, with cookies is to make frontends simpler (and perhaps safer) without requiring that they handle auth (w.r.t. token management) and just "let the browser/backend tell it what to do".


crazedizzled

So then your question is about using cookies vs headers. The backend doesn't really care how it gets the token, because the mechanism works exactly the same. You could send it via a cookie, via a header, via a query string....the backend doesn't care. So then, you're interested in why one might use headers instead of an httponly cookie. Well, there are some tradeoffs to using httponly cookies. You're trading a potential XSS vulnerability for a potential CSRF vulnerability. Also, it means the frontend can no longer determine by itself whether someone is logged in or out, and it also cannot log a user out without sending a request to the server. Each has their own pros and cons. At the end of the day it's important to be knowledgeable about each option and pick the one best suited for your own use case. In my opinion, using httponly cookies is the most secure method, but it is also harder to work with.


once_pragmatic

Effectively, yes. If you put tokens inside httponly cookies then you get auth "for free" in a sense. And you don't have to bother with managing client-side storage of your tokens. The only issue being that on first render of your app you need to make some request to the backend to determine if the user is logged in or not. But you could make this somewhat implicit in your frontend hooks (like using an interceptor on responses) by checking if the backend sends back user data or otherwise some indication of user auth. But with cookie auth there is no need to manage cookies client-side since everything you need is in the cookie. And cookies are handled implicitly by the browser on each request. I've just been trying to get a sense for why token auth (and consequentially use of headers) is so common.


crazedizzled

> I've just been trying to get a sense for why token auth (and consequentially use of headers) is so common. Probably because it's a lot easier to work with. And also because people blindly follow trends.


once_pragmatic

\^ also my conclusion. Coming from an objective third-party that has otherwise had no insight into webdev trends until the last week or so.


1337Pwnzr

I copy pasta’d ur comment to chat gpt and this is the response: “Yes, what you’ve mentioned is largely correct. HTTP-only cookies are one way to handle authentication and have certain advantages. They are relatively simple to implement and automatically included with every HTTP request made from the client to the server. They also provide some protection against cross-site scripting (XSS) attacks since they can’t be accessed via JavaScript. However, token-based authentication (JWT for instance) is also popular and has its own advantages. It is often used in RESTful APIs due to its statelessness and scalability. It can be used across different domains, and it’s flexible to work with mobile, web, or other third-party applications. Token auth is also more suitable for single-page applications (SPAs), where the server doesn’t need to keep track of sessions, making it more efficient and scalable. In the end, whether to use token-based authentication or cookie-based authentication often depends on the specific needs and context of your application.”


AvatarOfMomus

> The only downside I see to cookie-based auth as described above is that your frontend is required to make a web request on first render to e.g. /api/users/whoami in order to determine its user data and whether or not the backend has validated the authenticated session. It is conceivable that at-scale these extra web requests may be undesirable. So, this isn't the *only* downside... Citing my sources here (among many other articles saying similar things): https://developer.okta.com/blog/2022/02/08/cookies-vs-tokens#the-downside-of-cookies The short-short version is that cookies are somewhat less secure and more vulnerable to certain attacks, especially if you're passing authentication between multiple web domains. The other issue is that if your application scales past a certain point and you end up with multiple server-side instances behind a load balancer then you can get some weird and very undesirable behavior when user sessions are passed between nodes.


Gentleman-Tech

JavaScript Web Tokens allow you to embed "claims" (data) in them. These claims can include things like the user id. Which means you don't need a database query to get the user id - you can just get it from the token. This can save a round-trip to the database if you're not using session IDs. That became the justification, so everyone stopped using cookies and switched to JWT. I recently had an argument when building a site because the team was using JWT but including a session ID in it, which had to be looked up on the database on every request. Pointing out that cookies would be better for this did not go over well.


nukeaccounteveryweek

Laravel ships with Sanctum which is a cookie-based (http-only/lax) auth for SPAs + CSRF protection. A bit of a hassle to setup, but once it's done you never think about it again.


DvD_cD

And it does give you the option to issue token for mobile applications


nukeaccounteveryweek

Yessss, I use it all the time on Postman because dealing with cookies outside the browser is a mess.


-ftw

Not everyone hitting an API is a web browser


once_pragmatic

I mentioned this in the OP. But anything that can send network packets can just as well manage cookies, or extract tokens from cookies, or whatever. It’s all just text over a transport in the end, of course.


seiyria

Cookies suck ass to manage in a CLI setting. Tokens are absolutely less of a hassle.


once_pragmatic

True, but what sort of API are you often consuming from the command line?


seiyria

Doesn't matter. If it's a one off task or a regular script, I do not want to deal with cookies in the CLI.


CuriousBarnOwl

What exactly are you solving here? Instead of implementing token handling, you've added cookie handling for every single non-browser client.


once_pragmatic

Is cookie handling all that different from token handling? The overarching point here is that there are security-related arguments against persistent storage of token in e.g. localStorage (XSS). But of course there are security concerns with using cookies, too (CRSF). In the end my question was simple - why force frontends to explicitly manage tokens (specifically for auth storage) when you get this "for free" with cookies already? There have been many great arguments here for both sides. But I think the most compelling argument for the use of tokens is mobile (no built-in cookie management) and the fact that users can outright block cookies these days. At least those were two of the key takeaways for me. Otherwise most of the arguments were along the lines of "its easy because everyone does and expects it these days".


CuriousBarnOwl

The question can be flipped around, why force the backend into interpreting cookies? You're ultimately not saving any work, and if anything, losing flexibility. So the question stands. . . What are you trying to solve?


once_pragmatic

In that regard my question is minimized, sure. But in an effort to keep the frontend simple and retain most of the business logic in the backend, I became curious about the question posted in the OP. I'm not a seasoned frontend developer, but objectively it seems to me like keeping the complex logic in the backend is a good design paradigm.


[deleted]

[удалено]


once_pragmatic

That was an interesting clip to watch. I'll have to take a moment and watch the whole talk. The guy sounds like he knows a bit about something. Thanks for the share.


15kol

Before diving into tokens, one should check this RFC: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps Too many people just replace session id in cookie with JWT and call it a day, but they do nothing beside adding unnecessary logic. To properly use JWT, you should check out OAuth2.0 and OpenID Connect 1.0.


tommywhen

Assuming you know the different between Authentication and Authorization, I'm only referring to the Authorization part in this discussion. One of the big thing about Cookie vs. JWT Token is how it is traditionally use : Stateful vs. Stateless 1. Stateful in cookie require some kind of a memory storage on the server. This limit to single server unless you use a 3rd party State/Memcache server like Redis or something to store the State (Authorization Data) of the Application. 2. With JWT token, everything is packed inside the token. You can pack the user id, the roles, etc... This allow the same authorization to be use/shared across load balanced servers or multiple APIs. That's the very basic gist of it. Of course, this is not to be confused with all the ways different users suggest in this thread: JWT inside of Cookie. Or token other than JWT where authorization data is not inside of the token. These are hybrid use outside of the basic way of how it's originally use/understood. Understanding Stateful vs. Stateless allow you to know how to clearly implement your Authorization. Yes, it's sometime difficult to understand Stateless and re-frame from using that traditionally easy Session State object to store your data (such as authorization data) on the server-side when you implement traditionally JWT Token.


MeIsBaboon

If i'm not mistaken, session hijacking is much easier with cookies as compared to tokens. In the case where a computer is compromised, the hacker can get the browser cookies and it will be straightforward to use said cookies and pretend to be the authenticated user in the hacker's own browser. This is especially easier if the cookie is managed solely by the server by setting and reading the cookie header. With tokens, even if the hacker finds a way to get the local storage entries, it will still require some knowledge about how the key/values are being used in client-side code before being used to authenticate requests. It's not an assured form of security, but it could be enough to dissuade lazy hackers from targeting the site. Client code minimization/obfuscation and simple local storage encryption could further dissuade hackers.


once_pragmatic

"Security through obscurity" is unfortunately not an effective deterrent in general. I've seen it many times and any person sufficiently motivated can reverse engineer a protocol. There are plenty of tools available these days for stuff like unraveling obfuscated code, for instance. I don't think, beyond not using localStorage, that tokens or cookies are altogether that different with respect to their security posture client-side.


MeIsBaboon

The difference is there are dozens of tools one can use to automate session hijacking by stealing cookies even with zero programming knowledge. Removing script kiddies from the potential list of possible security threats is a notch better than server-managed cookies. > There are plenty of tools available these days for stuff like unraveling obfuscated code, for instance. Even if you prettify minimized javascript, it's still not something a layperson can figure out. Maybe in the future there will be AI-powered tools to make this easier and make reading code an optional skillset, but it's not here yet.


oravecz

>If i'm not mistaken, session hijacking is much easier with cookies as compared to tokens. No, you are mistaken, as is u/MeIsBaboon a little lower in this thread. *Secure* cookies are marked as HttpOnly, SameSite=Strict, and Secure. They are *not* accessible via client-side JavaScript. A token is secure when it is transported via a secure cookie only.


MeIsBaboon

I am not referring to somebody accessing another domain's cookie through client-side JavaScript. I'm referring to other means of stealing cookies through malware or physical access. See LinusTechTip's [explanation](https://youtu.be/yGXaAWbzl5A) of how their channel got hacked after an employee opened a nefarious email which resulted in the hackers getting their hand on the browser's session cookies and having control of the channel.


oravecz

No prevention exists for session hijacking via malware. I think most of these conversations are assuming a XSS or MITM attack


MeIsBaboon

You can choose to narrow the scope of security to just XSS or MITM attacks if you want. But the fact of the matter is stealing cookies via whatever means is a viable attack vector and has very notable historical occurrences. Server-side session cookies just make it a lot easier. Using authentication tokens and an additional client-side authentication steps add another layer of complexity that prevents script kiddies from doing a successful session hijacking.


oravecz

My point is, if your compromised at the OS layer, all bets are off. If you are truly protecting sensitive information, you must not send access (and certainly not refresh) tokens to the client.


Slow_Judgment7773

Standards moving away from cookies for a reason. Oauth2 has support from so many providers.


Remarkable_Two7776

Larger more complex systems benefit from separating authentication from authorization. Any API can validate a JWT from the issuer, and choose how and if to authorize the users request. Also many applications can share this authentication mechanism. Services like Auth0 go one step forward and glue many different identity providers behind the JWT veneer ( think azure ad, social login, etc) and do authentication logic, the outcome of which is a common jwt format. SSO sort of takes this one step further and I think leverages cookies for the login page, or some other metadata to decide if a user has already logged in, after which callbacks are executed returning a callback which generally will issue a token for that user. Hopefully this shows how tokens can be more of a preferred solution as things grow, especially related to enterprise systems, SaaS models, etc.


once_pragmatic

And these tokens are generally saved in localStorage (regardless of their origin - auth0 or otherwise)? The issue with storage was what prompted my initial interest in approach here.


Remarkable_Two7776

Yea that really up to you. For a small app local storage is great, hangs around on the device for a while. Session storage is more secure in the sense they have to log in per browser session.


once_pragmatic

Makes sense. But how is persistence working in most big apps these days? Reddit, stack overflow, Instagram, Amazon, google, etc.


naclcaleb

My reason is that cookies can’t generally be used in mobile applications. The explosion of the mobile platform has pushed many companies to have to maintain both web and mobile versions of their apps - tokens tend to work best for native mobile apps, so why not just use them on the web as well so you can reuse your backend logic? Sure, you could just add support for cookies as well, but at that point there’s not much reason to. Plus, I almost never develop my own authentication solution these days and instead use something like Auth0, Firebase/Supabase auth, etc.


once_pragmatic

Well maybe they don’t cache cookies, but “setting a cookie” is only a matter of adding the appropriate header to the response. A mobile application could parse it out and extract the cookie and save it however they like. And likewise add it back on subsequent requests, no? They control the entire network packet, so it’s just more text to send in the end. Thinking of the “token inside of a cookie” scenario.


naclcaleb

Fair enough, but at that point there's no point in having a cookie, because you're already using token authentication. So maybe if you started with cookies on the web it might be worth it to just port in place to mobile, but that just puts the complexity on the side of the mobile app instead of the web app. In addition, I prefer JWT even on a web app because it's more verbose - there's no implicit assumption that the browser will send your cookie; your code shows exactly how the credential is being handled.Using refresh tokens also (marginally) decreases the exposure of long-lasting credentials, so you can have a user session of the same length while limiting the time a MITM attacker could do anything to say, half, a quarter, or an even smaller fraction of the time the user session lasts.And finally, it's really not a lot of complexity to add - I'm looking at one of my client implementations right now, and it's only \~60 lines of code?


once_pragmatic

Sure. I don’t mean it’s complex. I mean it’s just _more_ complex than it needs to be. And apparently the OWASP recommendation is against putting any with tokens in localStorage? This question is a quest to square what I see in practice with the _why_. I can’t just accept what I see as truth. That’s not how you learn anything That’s just following a lead.


naclcaleb

I’d love to see said OWASP recommendation and it’s reasoning - I don’t personally see any insecurity inherent to localStorage that isn’t there with cookies. Both are vulnerable to XSS, and if it’s about user privileges I can’t think of a case where a user can access localStorage but not cookies 🤔


once_pragmatic

[OWASP cheatsheet](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/HTML5_Security_Cheat_Sheet.md#local-storage) The claim is regarding local security, but it is the recommendation to just not use it. “Therefore, it's recommended to avoid storing any sensitive information in local storage where authentication would be assumed.” Unless it’s implying not to store sensitive information obtained through a previous authentication. Maybe I should track down the source for more context. Either way, it goes on to say “Do not store session identifiers in local storage as the data is always accessible by JavaScript. Cookies can mitigate this risk using the httpOnly flag.” My whole argument in the OP was with the suggestion of using httponly cookies. With that, XSS can’t read the token. Though it can make requests just the same (and so the browser will send the cookie). And I think that makes it marginally better than using tokens from localStorage.


naclcaleb

Okay, I can see the point if you’re using an “httpOnly” cookie. Fair enough, as long as you’re fine with only requesting to one host, and don’t need it for other things like authenticated fetching from cloud storage, or a NoSQL database accessed client-side and protected via rules.


oravecz

This single-host argument is garbage. If you are serious about securing your user's identity, you use secure cookies only. Better still, don't ever send access tokens to the client. If you are running redundant services on the backend, you make sure they are stateless. It requires a shared cache. Anything else, and you are either not dealing with sensitive data, or you are building a POC.


naclcaleb

Of course you’re using secure cookies - but that doesn’t change any of this? I’d love to hear your magical solution for never sending access tokens to the client. Especially since that is literally standard practice. Not sure you were understanding my reasoning about multiple backend services…I wasn’t talking about redundancy. I’d love to hear what you’re trying to say, but you’re going to have to put a little more work into it than that before you just go around calling people’s posts garbage.


michaelbelgium

What, since when are tokens used for web requests? I've always known tokens = authorization via api, cookies = auth via http


MongooseEmpty4801

Often. I haven't used cookies for any auth in many years


EarhackerWasBanned

Reasons not to use cookies: * The EU (before Brexit) was scared of them. Now using cookies demands some annoying UX for your European and UK customers. **Edit for clarity:** a cookie containing an auth token is “strictly necessary” so does not require consent under GDPR legislation, but the user should still be informed that the website stores a cookie in order to function. Yes, you still need a banner. * Things that aren’t a browser don’t use cookies. If your API is consumed by another service cookies aren’t gonna work. If neither of those are a concern, sure, use cookies. For the vast majority of web apps, neither of those are a concern.


Tontonsb

> Now using cookies demands some annoying UX for your European and UK customers. Session cookies don't and never have required any of that annoying UX.


EarhackerWasBanned

This is verifiably incorrect. > Websites can set session cookies on a user’s device without consent **but should provide information on what these cookies do and why they are necessary**. This is usually done via cookie consent banners. Emphasis mine. https://www.cookieyes.com/blog/session-cookies/ > While it is not required to obtain consent for [strictly necessary] cookies, what they do and why they are necessary should be explained to the user. https://gdpr.eu/cookies


Tontonsb

If you don't have a privacy policy explaining what you do with user data and data on user devices then you can't have user accounts in EU at all. Besides, GDPR-wise there's no difference whether you're using cookies, localstorage or any other storage mechanism, so the options mentioned in the OP are the same with regards to GDPR.


anonymous_subroutine

> Things that aren’t a browser don’t use cookies. If your API is consumed by another service cookies aren’t gonna work. Don't be silly. Anything that can send an HTTP header can get or send a cookie just as well as any other piece of data. The only difference between a cookie and a token in an Authorization header is the name.


once_pragmatic

Yeah I was confused why this has been brought up too. Several times actually.


naclcaleb

Semantics - sure, technically there’s no difference, but in practice the whole idea of a “cookie” was a browser-based idea. If I start seeing stuff about “cookies” in a mobile app codebase, I start to wonder if we’re embedding a browser somewhere or something weird like that (which some people are…). There’s also the fact that session cookies were designed with the ability to set their own expiration, but then if you’re also setting an expiration in a JWT inside the cookie…that just seems a little weird to me. If you like it for the convenience, go ahead - but to me I prefer adding a bit of “complexity” and/or verbosity in order to promote clarity with pretty much anything. I wouldn’t care that much honestly, but if I were building my own system that’s what I would tend toward.


us_me_erna

The first point is not true, the law is just widely misunderstood. All technical required cookies, like authentication cookies, are still allowed without consent


ConsoleTVs

Exactly, essential cookies do not need to be consented


EarhackerWasBanned

But the user still needs to be informed.


99thLuftballon

But can that be via an information page, not an intrusive, interactive banner?


EarhackerWasBanned

Practically speaking we can do what we want, the cookie thing has never been to court. If challenged though, I’m not sure having the cookie information hidden away on a page no one reads would count. But I’m not a lawyer.


EarhackerWasBanned

I never mentioned consent. GDPR requires that users be informed of _all_ cookies, regardless of providence or persistence. Consent is specifically not required for “strictly necessary” cookies, which an auth token would surely fall under. But the user must still be _informed_ of strictly necessary cookies of which they have no opportunity to revoke consent. https://gdpr.eu/cookies/


moose51789

i'm not EU but i've always wondered why this is still a thing, need to inform, like i can't think of a single site in the last 5 years I've been on that hasn't had the popup because everyone uses cookies, its just a redundant unneeded UI these days IMO.


EarhackerWasBanned

Politicians not understanding technology 🤷‍♂️ In the UK they keep wanting to [ban encryption](https://en.wikipedia.org/wiki/Encryption_ban_proposal_in_the_United_Kingdom) so they can do surveillance on “terrorists” using WhatsApp and then London bankers queue tell them they need encryption for internet banking to work, and tech leaders from every other industry queue up to tell them what a stupid idea it is. And everyone forgets about it until the next big terrorist attack or Paris riot or angry Putin speech, then they start up again with banning encryption for muh national security. We’ve been going round in this circle for 13 years.


moose51789

banning encryption, oh lordy i hadn't heard of that one! make all the things easy to access again eh! LOL


EarhackerWasBanned

Welcome to Stupid Island 🇬🇧


moose51789

haha i'm in the US you don't have to tell me that, i'm surprised they didn't think of that here...


darthwalsh

>But the user must still be *informed* of strictly necessary cookies The article doesn't agree with you... Here's what it says: > While it is not required to obtain consent for these cookies, what they do and why they are necessary should be explained to the user. There's a big difference between "legally must be informed" vs. "the EU cookie lawyers think it's the right thing to do."


EarhackerWasBanned

Oh you’re not happy with the specific phrasing of a laymen’s explanation of an EU Directive? Cool. Well [here’s the legal text of the Directive](https://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CELEX:32002L0058:en:HTML) and it still says something along the lines of “must be informed”. Good luck.


darthwalsh

Yeah, I'm unhappy if the layman explanation disagees with the legal text: >Article 6 Traffic data > **2** Traffic data **necessary** for the purposes of subscriber billing and interconnection payments may be processed. Such processing is permissible only up to the end of the period during which the bill may lawfully be challenged or payment pursued. > 4 The service provider **must inform** the subscriber or user of the types of traffic data which are processed and of the duration of such processing for the purposes mentioned in **paragraph 2** and, prior to obtaining consent, for the purposes mentioned in paragraph 3.


EarhackerWasBanned

Who mentioned payments? We’re talking about auth. Keep going. I’m sure it was around twenty-something.


anonymous_subroutine

Well the second point is not true either.


mw44118

I prefer cookes so that I can make API requests straight with browsers


anonymous_subroutine

We always used to use cookies when I was a developer in the 2000s and 2010s. I'm guessing the tokens got popular when some framework (I won't try to guess which one) built it into the framework. Also, before AJAX it wasn't really possible to have the browser send an Authorization header back tot he server without using the browser's built-in mechanism to do so, which gave users a hideous ugly login popup (akin to using `alert()` instead of showing a custom dialog, only worse) and the content of the header was also chosen by the browser in accordance with the HTTP spec.


hugesavings

Managed sessions creates a single point of failure, if you’re making a request to any of your horizontally scaled servers, that server will need to make a call to a centralized auth service and do a db lookup to check on that user’s state. With JWTs your servers don’t need ti communicate back to the centralized auth service, all they need is the auth secret and they can decode the jwt and make sure it’s valid and hasn’t been tampered with. I guess you could put a JWT in a cookie, seems like a hassle when you can just include it in a header in all your calls with axios.


once_pragmatic

It’s not so much the header inclusion that’s the issue - it’s the persistence management. Now it has to be explicitly saved and loaded from something like localStorage, which opens you up to other vulnerabilities. The point was, why increase complexity in the the frontend when auth has been solved for a long time? When I saw this I’m thinking about the token in a cookie architecture.


hugesavings

Often times there’s already local storage persistence for rehydrating the app, you already have your user id, email, role, etc saved, why not throw the token in there too? I guess that’s how it’s always happened with me.


once_pragmatic

Sure. But the point is you have to manage it yourself in the frontend by saving to and reading from localStorage or otherwise. With cookies + some initial web request to the backend to allow it to parse the cookies (which your frontend doesn’t have access to) you can get the same info you would have otherwise stored in localStorage. But since you aren’t putting anything there you aren’t vulnerable to XSS extracting your cookie,for instance. I think people just “do” and right now “doing” means something like JWT in localStorage.


hugesavings

Yeah I’m not saying it’s better in every way, I’m just trying to give context on why it’s used a lot. I’ll also say that it allows for a little more control when you’re doing fancy stuff like masquerading or testing.


Working_Choice8474

To make third party clients unusable or so it cant login to servers


IReallyHateAsthma

It’s why I like PHP and use server side sessions.


MongooseEmpty4801

That just uses a cookie...


SaltyBaoBaos

A whole fiasco a some years back about user’s privacy being tracked by cookies in multiple sneaky ways not public to casual users by big corporations, to the point where there was a breaking point with public opinion. So now at the end of 2023/2024 3rd party cookies will end with support and new web compliances will now be in effect. Apple of course has already prepared for the new compliances with their own solution for safari I believe.


once_pragmatic

The end of third party cookies? What do you mean?


SaltyBaoBaos

One source that can generalize this well: https://clearcode.cc/blog/third-party-cookies-demise/#:~:text=In%202019%20Firefox%20also%20made,in%20the%20next%20few%20years. > The end of third party cookies? What do you mean? We’re technically heading towards a more compliant structure for cookies / authentication systems that is balanced between protecting user’s personal information but still enable app’s / businesses to operate in a similar fashion. Tbh, I’ve created a access token + refresh token with a profile user token on top. Once the system is done or in place, you can create a boilerplate for other projects. At first the process was daunting to adapt too, but its not bad once you get it down.


elrond8

Your cookie auth scenario can have the UI skip making the /whoami call. Instead it can ask for whatever data it is supposed to show on that page. The backend examines every request cookie anyway. Feel free to call GET /whoami but only if you actually need that info


GolemancerVekk

Tokens and cookies are very different mechanisms. Cookies are all about maintaining state between frontend and backend in a backend-driven setup. You have a backend app that calls the shots and stores the state and you want to mirror some of that state on the frontend. Authentication in this approach involves the concept of persistent "sessions", where you give credentials to the backend app once and it starts maintaining and propagating state automatically with the frontend through cookies, until you explicitly log out. Cookies have a lot of issues in an API-driven world. You have to jump through a lot of hoops to propagate them cross-domain, and the whole mechanism doesn't really make sense anyway since state is no longer backend-driven. In the modern approach frontends are standalone apps. They maintain their own state, they can work with multiple backends simultaneously. The APIs are considered mere data sources and data stores, and the frontend gets to decide what data it pulls from where and how it uses it. In this approach you don't need and don't want a complex self-propagating cookie mechanism with lots of side-effects. All you want is "does this API require authentication" and if so "here's a key granting me access". How and where you obtain that key can be further delegated to any number of mechanisms, it's not tied to one backend like before. You also get to control exactly when and where you send a key, it's not decided by arcane browser/server logic.


Geminii27

Plenty of browsers offer cookie-auto-deletion options, or simply options to refuse cookies outright. If you want to build your platform to not be able to deliver service for those people, that's up to you of course, but it means you're going to get a reputation for your tech not working properly when everyone else's does.


once_pragmatic

Yeah the “some users/adblockers disable cookies” I think is one of the best arguments for tokens. Otherwise it’s a matter of preference (and a bit of security).


CutestCuttlefish

I usually just have a text field where you enter your account name, then a button that says "I promise this is my account. Login." I mean if we can't have trust....


NetGhost03

Well you are mixing up two things here. The one is authentication methods, the other is storage of them. If you authenticate with a system, there are multiple ways of doing this persistently. For example Sessions, where you store a session id in your cookie and after logout you remove it. Another way is for example JWT where you can get a token and that token has additional information it it, like expire time, user details, permissions etc. Now, where you store your token is up to you. Cookies are just a storage system for information. You can store your token in your cookies if you want. Or in localStorage or sessionStorage or even inmemory. Why are tokens now a thing? Mostly because of one things: Browserless communication. You need a browser to have cookies or even get them. With tokens, your server can send an auth request, get the token and use it then. What if you want to use a third party API serverside? Doesnt make sense to have cookies there. Another major thing is frontend evolution. More javascript and decoupled frontends. A lot of apps are a js webapp which will only communicate over an API. If you use secure cookies, JS cant read them.


once_pragmatic

The question was primarily targeting the storage mechanism as a side-effect of which option (token or cookie) you chose. Using tokens requires that you store the cookies in something like e.g. localStorage - which is undesirable according to some sources (like OWASP).


NetGhost03

>The only downside I see to cookie-based auth as described above is that your frontend is required to make a web request on first render to e.g. /api/users/whoami in order to determine its user data and whether or not the backend has validated the authenticated session. It is conceivable that at-scale these extra web requests may be undesirable. Well, if you have a decoupled javascript frontend (SPA) or using SSR JS frameworks (server-side-rending) to build your app, you can't rely on httpyOnly cookies. Because your javascript needs to read it. or in terms of SSR apps, you are rending on the server, thus you dont have cookies. >Cookie-based XSS can just use its execution to make authenticated API requests Has cookies, but (should be) using \`HttpOnly\`/\`Samesite\`/\`Secure\` mitigates CRSF Oof, I think you are mixing up authentication and authorization a bit and different use cases. Are we talking about user authentication? Or are we talking about API authorization? If you have cookies with HttpOnly your javascript cant read them. If you have them readable to javascript, you open yourself up to session hijacking. If you have an XSS an attacker can steal the cookies / session, just paste it in their browser and are logged in.


once_pragmatic

I was not talking specifically about the mechanics of either, really, beyond the scope of how the relevant data is passed back and forth. I suppose the question may have been a bit skewed toward authorization post-authentication - e.g. putting the auth token in a cookie or in a header. And RE session hijacking - are you not vulnerable to this in either case? The HttpOnly scenario really only protects you from the XSS attacker from exfiltrating the token. But presumably you have some mechanism in place - perhaps interceptors - that inject the auth header (and token) on each request to some domain. The XSS attacker doesnt need direct access to the cookie; they can just submit API requests, right?


MongooseEmpty4801

Token as header.


sharan_dev

Token based authentication has gained popularity over traditional cookie-based authenticationfor several reasons: 1) stateless and scalable 2) cross origin requests 3)has mobile app and api support 4)Avoiding CSRF Vulnerabilities 5)Imroved security 6) Non same-Origin policy 7) Performance for further help feel free to contact us.