There are a couple of ways to keep tokens on the client that prevent malicious code from accessing them.
- use HTTPOnly secure cookies. These will not be accessible to malicious JavaScript but can only be sent to servers on the same domain. Well, I guess if there was an exploit that let JS break the sandbox and access cookies, they could be accessible, but I think we can trust the browser vendors around this kind of security. This approach is widely supported, but does expose the token to physical exfiltration (that is, if someone on the browser opens up devtools, they can see the cookie with the token in it).
- store the tokens in memory. As far as I know, malicious JS code can't rummage around in memory. This works for SPAs, but does break if the user refreshes the page.
- bind the token to the client cryptographically using DPoP. This is a newish standard and isn't as widely accepted, but means you can store the token anywhere, since there's a signing operation tied to the browser.
All of these can work and have different tradeoffs.
I can't use http only cookies, because I have no server to set them. I'm using JavaScript on the client to do the post to get the tokens. Storing in memory is mostly fine, though I do want them in a cookie. May be able to skip that.
I will look into the dpop thing. A bit limited as I'm using AWS cognito.
I confess my thread model is such that I think I am fine with storing token in local storage. Would like to be using standard practice, though.
I'd be a liar if I said I had fully modeled things. I apologize for making it sound like I hadn't given it any thought.
I was hoping I had missed some updated guidance on how to manage tokens. Way too much of the documentation I was finding on OpenAPI and OAuth seemed to be aspirational and referencing things that hadn't come to be, yet. It has gotten rather frustrating.
Thanks for the link, it is a surprisingly fun topic to read on.
- use HTTPOnly secure cookies. These will not be accessible to malicious JavaScript but can only be sent to servers on the same domain. Well, I guess if there was an exploit that let JS break the sandbox and access cookies, they could be accessible, but I think we can trust the browser vendors around this kind of security. This approach is widely supported, but does expose the token to physical exfiltration (that is, if someone on the browser opens up devtools, they can see the cookie with the token in it).
- store the tokens in memory. As far as I know, malicious JS code can't rummage around in memory. This works for SPAs, but does break if the user refreshes the page.
- bind the token to the client cryptographically using DPoP. This is a newish standard and isn't as widely accepted, but means you can store the token anywhere, since there's a signing operation tied to the browser.
All of these can work and have different tradeoffs.