There are two ways you can save authentication information in the browser:
- HTML5 Web Storage
In each case, you have to trust that browsers are implemented correctly, and that Website A can't somehow access the authentication information for Website B. In that sense, both storage mechanisms are equally secure. Problems can arise in terms of how you use them though.
- The browser will automatically send the authentication information with every request to the API. This can be convenient so long as you know it's happening.
- You have to remember that CSRF is a thing, and deal with it.
If you use HTML5 Web Storage:
The big difference people care about is that with cookies, you have to worry about CSRF. To handle CSRF properly, you usually need an additional "synchronizer token".
Some other differences are discussed here.
edit a google search reveals this for asp.net - they call the synchronizer token a "request verification token".
The best way to protect your access token is to not store it client-side at all.
How does that work? Well at the point of generating the access token, generate some other cryptographically secure PRNG (which you map to the access token on the server), map this to the users session ID and return this to the client instead.
This will reduce the attack area because what you are now returning is a token tied to a session, and both would be required in order to authorise the token. When the session expires so does the token, naturally, and the user would be forced to re-authenticate thus generating a new access token.
It's still not 100% secure, however, you need to weigh up the possibility of something like that happening within a users session. Based on that, you can then tweak your session/token expiry times to suit, although you also need to be wary of usability - you don't want to be expiring sessions after 5 minutes as having to log back in constantly can be tedious (or maybe you can, depends on the type of application).
I'd store the token in a cookie with the following three flags: 1. Secure: transmit over https 2. HttpOnly: client-side JS cannot read it (XSS protection) 3. SameSite (either Lax or Strict): CSRF protection
In this way you are immune to XSS and CSRF. You only need to be careful about SameSite, as it is relatively new and only got recently supported by the 4 major browsers (Chrome, FF, Safari, Edge) see: https://caniuse.com/#feat=same-site-cookie-attribute
For more info regarding cookie hardening see https://odino.org/security-hardening-http-cookies/
Alex's blog must be informative.
A server dies every time someone implements OAuth in a single page is web app. Stop the genocide! Use a server side proxy! Act now!
You need to send the token to server in every requset. So it doesn't matter you store it in cookie or html 5 storage. Both are secure storages and eveyone who has access the client machine has access to the token too anyway.
But I recommend do not use the submitted token in cookie on your server to prevent CSRF attack. I think it is good idea to manually include the token in every request you make whenever required.
Using cookie also makes the request header bigger which is not appropriate.