2

I am having a lot of trouble with claims that are used to check user permissions in the controllers.

App structure

Our backend is .NET Core, the front end is React, and for now we only allow logging in using the google API using a google enabled email. We generate a JWT and store it on the browser's localStorage, then send it on every request. Also, there are no roles: if you are logged then you are an Admin.

The devs that did the app's "skeleton" are gone now, and it's my first time on security concerns dealing.

The new requirement

We need now to implement roles and permission, and it seems MS expects one to use Claims for this. I did this and added those claims to the jwt, then added policies on the config and it actually worked. If you have a specific claim you can access a specific controller or method, otherwise the server returns a 403 error.

But then I logged in with an actual admin role, copied the localStorage value using devtools, and then logged off and back in with a user with almost no permission. When I pasted the local storage entry (again, using devtools) I immediately got all claims and was able to access every controller and method the admin could.

It seems the proper way to go then should be using a HttpOnly, secure cookie, perhaps with "SameOrigin" set to true (not sure how this affects Single Sign On), but I do not understand how to do that. I have seen blog posts, even downloaded an app (that I could not make run but I copied code over to my app), but I keep failing. Also I don't understand if I need to do anything for the cookie to be used when checking the controller policies.

Can anyone give me a hand on this?

Alejandro B.
  • 4,807
  • 2
  • 33
  • 61

1 Answers1

0

The thing is that if an attacker is able to get into user's browser he/she can probably do much more damage than just stealing an access_token. Check this thread on Auth0.com. Basically:

Let's say you are in a position to steal a JWT from someone's browser. Depending on how you are able to do it there could be two scenarios:

  1. You are either in a situation to cause a lot more damage than just stealing a token.
  2. You are not, imagine if instead of storing a JWT your actual password got stolen, that would be much worse.

The main difference is that cookies are more vulnerable to XSRF while JWTs are more vulnerable to XSS.

Also, one more useful quote if you'd choose cookies over JWT:

The PROs for cookies are:

  • Safer against XSS assuming you are willing to use HttpOnly cookies

The cons are:

  • You can't access the JWT in JS code.
  • You need to protect requests against CSRF, as the header approach would not be vulnerable to this but cookies are.
  • Your API code needs to handle JWTs coming from cookies (from browsers) or from headers (other servers calling your API will need to use a header).
  • Cookies work if your API is on the same domain as your site. It is not usable in case the API is on a different domain.

When it comes to third point about validating JWT from a cookie instead of http headers you would need to modify the middlewares as described here.

Personally, if you use ReactJS I would keep the JWT model because it's more suitable for SPA applications. Being in a situation as you describe: "When I pasted the local storage entry (again, using devtools) I immediately got all claims" basically means that an attacker is sitting in front of the computer in which case stealing the JWT token becomes little of concern.

Just keep in mind that you need to set an expiration date to your JWT tokens and then you should be fine.

Ivan Sivak
  • 7,178
  • 3
  • 36
  • 42