IdentityModel / oidc-token-manager

Apache License 2.0
51 stars 36 forks source link

How secure is the storage of the access token? #30

Closed thj-dk closed 8 years ago

thj-dk commented 8 years ago

Hi,

I'm having a hard time figuring out how secure the approach of storing the access token in localStorage is. I was hoping that you would explain your view on it, and what you're doing in order to prevent attacks.

We have IdentityServer3 issuing tokens to authenticated users, and an API that expects requests to be authorized using the issued access tokens. Then we or our customers have this single page JavaScript based application, with no backend, that needs to communicate with the API. Users authenticate with our identity server using the implicit flow or resource owner flow for trusted clients, and gets an access token in return.

Now oidc-token-manager can help me handle the identity server response and store the token client-side. Inspecting the source code, the token is stored in localStorage. There are lots of opinions on this subject, and many against using localStorage:

"Stormpath recommends that you store your JWT in cookies for web applications, because of the additional security they provide, and the simplicity of protecting against CSRF with modern web frameworks. HTML5 Web Storage is vulnerable to XSS, has a larger attack surface area, and can impact all application users on a successful attack." - https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/

"If you decide to implement this grant then you must be aware that the access token should be treated as “public knowledge” (like a public RSA key) and therefore it must have a very limited permissions when interacting with the API server." - http://alexbilbie.com/2013/02/a-guide-to-oauth-2-grants/

Now some of these tokens issued, gives lots of access to the user, and we need minimize the risk of begin attacked. Some recommends proxying all API requests, where this proxy enhances the request with the users' access token, so it's not exposed to the client. I guess that this involves using the authorisation code grant, and then handing the proxy application code to request the token on behalf of the user?

I'm confused. Can we securely store the token on the client in order to avoid proxying all requests? What are your takes on this problem?

brockallen commented 8 years ago

Cookies won't help XSS since XSS can submit requests the same as if the user click some button. Also, I guess I'm not clear on who's writing the cookie - client code or server code. If you're doing a pure SPA where you need something like the oidc-token-manager then you have no server code. If you're concerned, then I'd suggest using sessionStore not localStorage. The oidc-token-manager supports the ability to use sessionStorage (instead of localStorage).

But yea, if you do have server-side code/framework, then I don't see the need to use the oidc-token-manager library. It's still possible that you do need to make Ajax calls from JS, then you need to emit the access token into the JS/HTML, and XSS will get you there as well.

So XSS will get you every way (even if no APIs are involved).

thj-dk commented 8 years ago

The thing is, that I would like to keep it a pure SPA, and then just use the oidc-token-manager to manage the tokens. But I'm unsure about how secure it is since the cookie is stored client side. Lots of articles does not recommend this, and so I wondered what you're take on it is? And what you did with oidc-token-manager to make it as secure as possible (if you've done that)?

Could you maybe put some words on you thoughts about storing the access token client side?

brockallen commented 8 years ago

Well, XSS in any app is pretty much game over. The problem with storing tokens in localStorage or sessionStorage is that if any app under the origin is XSS'd then it's game over (sessionStorage helps a little).

thj-dk commented 8 years ago

Can/are you doing anything in oidc-token-manager to prevent/minimize it?

brockallen commented 8 years ago

sessionStorage is better than localStorage for that. You can also use CSP from your server, but again, it requires your all of your server pages to use it. So again, if you're just building one app that's hosted on a server with other apps, then you're subject to all those other apps not being compromised. Security is hard.

thj-dk commented 8 years ago

I'd guess that I have to do some more reading on the topic in order to determine what we need to do in our case. I'm guessing that the most secure solution is to proxy all requests through a middleware that enhances each request from the SPA with the users' access token. That way the access token isn't stored client side. What I need to do is to figure out how big a problem XSS is and if it's worth it, proxying all requests through a middleware.

brockallen commented 8 years ago

But you still need something from the browser to the server to authenticate. And if you have an XSS vulnerability then what you're proposing still won't solve your problem. That' why I said if you have XSS problem then it's pretty much game over. CSP will help a lot in preventing XSS.

thj-dk commented 8 years ago

Thats true, although it will be harder to obtain the access token, I guess. I'll have to look into CSP. Thanks Brock.