Reputation: 301
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?
Upvotes: 3
Views: 1854
Reputation: 1400
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:
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.
Upvotes: 5