3

I am trying to implement a role based access control system with react-redux. So far I've been reading up on it and have seen some general methods along the lines of:

<View>
    {!user && <LoginScreen />}
    {user && <WelcomeScreen user={user} />}
</View>

which is basically using variables or the state to test conditions and grant access to certain components. My predicament occurs when I came across this post:

Can react state be tampered with to bypass security measures?

If the user can tamper the state and view the components where they don't have permissions, what is the proper way to ensure role based access? Storing the user data as position: employee could be changed to position: manager in the client, and then they would be able to see what options are available to managers, even if no REST requests have been made.

I am currently using session cookies to validate the user server side, and any data-sensitive REST get/posts are authenticated - but how does this translate to the client?

user logs in -> server verifies -> server sends back session variable that holds user.position / or sends json(user) -> client looks at session from server or json(user), stores user.position in state.user.position -> state.user.position is used in conditional if to determine whether or not to display components as above ---*but*---> client goes in and changes state state.user.position and gets access to components anyways

If we can change state in the client, how can we securely use conditional tests in react/redux?

1
  • 2
    Never trust the Client! If an employee changes his/her role to manager, your client would try to get manager related data via an API call where the API then checks authorization and rejects. (as you said your REST api does) That means also that you don't load sensitive data beforehand and "hide" it. Commented Jan 25, 2019 at 20:46

1 Answer 1

5

Something like this is handled by back-end, not by React. Whatever you do, DO NOT just grab all the data and filter it in React. I have no idea how you differentiate users based off of your example, but, for simplicity I'll assume you're using JWT. In this implementation, a token is generated when you login, and you can safely store this in eg local storage or redux. For all api calls you make, you should attach a token to them. The back-end should then, for every call a logged in user makes, do a few things:

  • Verify the token signature
  • Grab the user id from token and grab permissions/roles
  • Check if user has access to the api call or not

That way, even if by some miracle someone changes the token and passes the verification, which isn't likely, the entry in the database remains unchanged, and will not let them access the data they're looking for.

You could protect API routes by role, or even more granular, by a specific permission flag. Since you're doing the roles, most back-end frameworks let you apply some middleware, so apply a role-check middleware for all admin calls, another one for all logged in user calls, and that'll save you a bunch of trouble.

Remember, whenever you do client-side filtering, you're putting all your security on the hackers' laptop.

Edit: Addressing the comment

JWT just provides a standardized approach to the issue is all.

Let's for a second assume that your session variable stores the following info {'userid': 5, 'position': manager}. So if I'm a nice attacker, I'll just change manager to admin, see where the gets me, but if I'm not nice, I'll try all user ids from 0 to 10000, both with manager and admin as the position, see where that gets me. So then you try a random user id, like a hash of the timestamp. Still, attack surface has only increased somewhat. Now you're mad at these hackers. You're like okay, I'm going to encrypt this session variable, but I can't really store the key in React, since that's hackable, I'll just attach the encrypted thing to every request, decrypt it, verify it, and approve if it's valid. At which point, you basically almost re-invented JWT.

Sign up to request clarification or add additional context in comments.

11 Comments

I was thinking of using JWTs for this but ran along a few people who advocated against it, one in a post being: cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions . I have a session variable that stores the user's information, for example position:manager. I suppose another way to word this entire question would be, how to securely obtain the session info and use it to display components without the client manipulating it. As soon as I retrieve session data and use it for test cases, it becomes a security issue as the user could change the input to change the display.
For example, if someone logs in and has the server authenticate them and provide a session variable along with the response of the user info - I can store user.position in state, which could theoretically later be used to determine whether components are displayed or not based on that condition. Problem is user can manipulate that state and gain access to the components anyways if we use conditional display.
I've somewhat addressed the comment by updating the answer. That's the thing - you can't store much in the state, except a token of some sorts.JWT contains user info, and is easily decryptable even without the key, but can't be verified unless the person trying to spoof has access to your secret. Some of the issues mentioned in the blog can easily be addressed. It's not a bulletproof system, but if the question is how do I know which user is what role, securely, that's the answer.
Okay let's assume there's a jwt with user.position inside - If you do something like decode(jwt) and get a hold of that, you would still store it in some variable or state before doing a conditional test on your components. At that point, it's if { some_variable_that_the_client_can_change === true? show() : deny() }
As I said it doesn't matter. Navigation items only take you to pages, much like <a href="#"> does, so I'll edit my token, make myself an admin, and I'll see 2 more menu items eg. I'll then proceed to clicking them, which will open the page, and the page will make another request for the data, which will be denied. So the biggest damage I can do is look at some more nav links
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.