React SDK / SignOn Widget - Cookies vs. localStorage

Based on this article, I’m wondering if there is a way to avoid using localStorage to store the JWT and instead to rely on cookies.


It is a best practice and recommendation from OIDF and IETF to use implicit flow for SPA applications. But the answer is a little more nuanced than that…

The problem with localStorage is it is vulnerable to XSS, the problem with cookies is it is vulnerable to XSRF. If you gather 10 senior developers together and ask which one is easier to protect against, you will get 10 different answers, even though there are only 2 options. @rdegges and I have different opinions here :slight_smile:

If you decide to store tokens in localStorage, you need to mitigate to your best ability XSS, if you store tokens in a cookie, you need to mitigate against XSRF.

The next point is somewhat important. It involves the difference between information and media. A lot of times when people look at this problem, in particular, they conflate the two. A stateless token (JWT) is the information, the storage mechanism is the media. Stateless tokens have the problem that if they are leaked, they can be reused in bearer header, regardless of the medium they are stored in.

If someone has a problem with storing stateless authentication/authorization tokens client side for browser-based applications, you shouldn’t be doing it, and go back session cookies (which are also vulnerable to XSRF and again this is the problem with the medium, not the information). I do not feel like this is the norm though, there are a lot of open source frameworks that help with the security hardening (like Helmet for Express)

So to answer your question, Okta’s React SDK does the best practice for SPA applications (implicit flow and storage of tokens in sessionStorage), if you need to do something different, you will need to drop down and use Authentication API through okta-auth-js, and use a server-side component for authorization_code, so you can correctly store the tokens server side and use session management in the server-side frameworks choice.

This is how our Spring / Express / .NET integrations work.

Hope this information helps, I feel like I got a little bit in the weeds, but there was a lot of information to cover. Let me know any questions!


@tom Thank you for the detailed response. I understand the tradeoffs involved and appreciate the benefit of the current implementation.

Heh. Hope that was useful. @tom and I have been talking about this stuff endlessly forever.

There are always different approaches. My personal article on my blog was meant to apply to the 99% of developers who blindly implement that pattern without thinking about the tradeoffs.

If you’re aware of the risks and OWASP guidance, etc., you should be fine. If security is a major concern and you’re building something sensitive like a banking app, might be wise to take the other approach. Any implicit flow will always have some weaknesses.