by mattrighetti on 6/4/25, 11:33 PM with 32 comments
by Goofy_Coyote on 6/5/25, 3:27 AM
Just a note that ‘HttpOnly’ doesn’t neutralize XSS.(although this is not the main point of this blog)
This is dangerously misleading. HttpOnly prevents cookie theft, but it absolutely doesn't "neutralize" XSS.
First, even with HttpOnly cookies, malicious JS can still make requests on behalf of the user - the browser happily attaches all cookies (including HttpOnly ones) to XHR/fetch requests. So an attacker can still
`fetch('/api/admin/add-user', {method: 'POST', body: JSON.stringify({email: 'attacker@evil.com', role: 'admin'})})`
or delete data, transfer funds, whatever the victim is authorized to do. They don't need to read the cookie, they just need the browser to send it.
This is why many apps ask for your password to change your email or reauthenticate you/trigger an MFA workflow when doing certain things.
Second, tons of XSS attacks don't even care about your cookies. They can rewrite the DOM with a fake login page and harvest credentials directly. They can keylog everything you type. They can steal data that's already on the page, redirect you to phishing sites, or mine crypto with your CPU.
HttpOnly is a good defense-in-depth measure, but calling it a neutralizer for XSS is like saying a seatbelt neutralizes car accidents. You still need proper input validation, (contextual) output encoding, CSP etc.
by johnduhart on 6/5/25, 3:04 AM
Okay, but then you implement storage of the refresh token and build this bespoke JWT re-issuance logic. So where's the win here? Just use sessions.
by ripley12 on 6/5/25, 1:35 AM
by 0x457 on 6/5/25, 6:33 PM
Use a normal session, since you already assume there is a db for authentication.
That JWT token takes much more space on a client (and sent with every request!) than a proper session cookie would.
That JWT refresh token would also take more space than what you store in claims would take up even if you naively stored it in DB (i.e. not via relation between user and session).
IMO, the only way to correctly use JWT for authz (authn is handeled somewhere else as it should):
- authenticate user somehow (not JWT probably, unless it's a federated login)
- issue a short-lived JWT with required claims
- pass that JWT with requests to other backends
- now backends can validate that JWT by themselves
by skwee357 on 6/5/25, 7:43 PM
But then came an era of SPA and we needed another way to authenticate users, since XHR did not (and still not?) supported cookies, so we created the signed JWT token.
I’m a bit confused as to why one would want to store JWT access and refresh token in a cookie? Axum provided both signed (temper proof but not secret) and private (allows you to save sensitive information) cookies. Why wouldn’t you use these instead of saving JWT in cookies?
by mrbluecoat on 6/5/25, 1:29 AM