Normal cookies are JS-accessible, but HTTP-only cookies should not be: "A cookie with the HttpOnly attribute is inaccessible to the JavaScript Document.cookie API; it is sent only to the server."
Ah thanks! This is new to me. That is indeed a concern, but probably can be worked around, e.g. by proxying requests to third party domains through the same Domain.
Which is why you use domain scoping, httpOnly and Secure cookie flags so they can only be read by matching hosts (with greater granularity than same-origin policy) over HTTPS and can’t be read by JavaScript. The Web Storage API does not offer these protections.
They can't be read BUT the browser will send the cookie with every request. If you have an XSS, it is game over. The attacker can just send requests from your browser. Slightly less convenient. You are merely taking away the convenience of the attacker doing the attack manually on his own browser, which he probably doesn't want to do anyways. If he can inject js into your site, he will make your browser send the request(s) to do the actions with your credentials in an automated and quick way. Your browser will send the cookie automatically. From the attacker, it would merely be nice if he could read your tokens, but it is absolutely not necessary.
Like some here, I don't understand the hate around keeping tokens in localstorage. People immediately say "but js can read it!" but so what? If someone can put malicious js in my site, it is GAME OVER, secure http-only cookie or not. When that is the case, the saner option is doing away with an old and misused invention called cookies. The upside with ditching cookies is that you are an order of magnitude safer against CSRF since your browser does not send anything automatically. You don't need to keep CSRF token state in your server(s) either (helps with scale, one less state to worry about), it is a win.
http-only secure cookies do not give you any additional security. Ditching cookies does.
I think some people don't realize that CSRF tokens are basically the same thing as bearer tokens (which JWT also does), but it's just that they get re-generated every time you open a new page usually. So it's a bit ironic when everyone screams that tokens are bad, but they're all using them to protect against confused deputy attacks.
I am talking about a much more general class of security than just XSS. You’re making perfect the enemy of good here - yes, of course XSS is not completely mitigated by httpOnly. That was not my point.
My actual point stands, the Web Storage API doesn’t offer the same protections as cookies. Don’t store sensitive data in localStorage, that is emphatically not it’s intended use.
>I am talking about a much more general class of security than just XSS.
And what would those be that are relevant to this discussion? The way we (ab)use cookies is arguably not their intended use either.
I can't think of a scenario in this context where an attacker says "damn he is using http-only cookies, I won't be able to do what I want to do"
The only pragmatic difference between both is js accessibility. That only matters when someone can inject scripts into your site. My point is, when that happens, cookies are also bust.
Store a security token in localStorage and additionally store a secure signature for it in a secure, HTTP-only cookie. On your backend, verify validity of both the token and its additional signature contained in the cookie.
I don't believe it adds any meaningful security that justifies the cost (development, testing, hardening, scaling the state across servers if necessary etc.) With security "more complicated" does not necessarily mean "more secure". Doing it without multiplying the number of ways things can go wrong is deceptively hard.
Yes, just that with regards to security I've seen to many burned by "it can't hurt" processes. With your suggestion, assuming perfect implementation, I personally can't see where it would help. Like, if attacker can run js in your site, they can just set the cookie as necessary before making requests (if the cookie does not exist already) since that is something they can already do. If the cookie exists (most likely scenario), the browser will send it with each request anyways so no added security there either.