Role based access control in React-Redux apps
Tags: react, rbac, redux, reacthooks
Published: 2020-06-18 02:07:06

This assumes you have a basic knowledge of react, react-router, redux and redux-middlewares. Also, you have already implemented authentication in the react-redux app.

*Note: I have used redux but the same can be done without relying on redux. So, while some knowledge of redux may help you understand what I have tried to convey, redux isn't a necessity.*

--------------------

While working in a project, the requirement arose to give the functionality of Role based access control (RBAC) in a client-side-rendered react-app.

Basically, the application was going to have multiple tiers of users with flexible permissions and depending on the permission granted to any particular user, a component or a part of the application may/may not become accessible to that user.

Implementing RBAC at the client-side can be divided into:
* Conditional rendering of the components
* Updating the conditions when permissions change

------------------------
## Conditional Rendering of the components:
There are many approaches that can be used for this. One of my initial approach was to wrap the component (say CheckedComponent) with a component (say CheckPermissions) which would conditionally render them based on the permissions given to the current user. This looks something like this:
{% gist https://gist.github.com/tometo-dev/96399c673c0621499b912a4674430f1d %}
*The user-permissions were stored in the redux-store route-wise.*

The above approach does the job but fails if the `<CheckedComponent />` also requires permission checking, basically making the whole process nested. Also, I didn’t know before-hand the depth of nesting.

I could also have used HoCs, but they too suffered from the same issue, in my case.

So, I decided to go with the hooks approach, which looks something like this:
* the `useAuthorization` hook returns the list of permissions the user has for the given route. This may seem repetitive as this could directly have been taken from the `redux-store`, but this hook provided a level of abstraction. Also, if the *permission-retrieval logic for the user is changed, only this needed to be changed and everything would still work*.
* each component is conditionally rendered based on the user permissions.
{% gist https://gist.github.com/tometo-dev/7a00825d4d808e4c6e2cc0120f1119f4 %}
In this approach, I need to do the same thing again and again, but looks neat for now.

-----------------------

## Updating the conditions when permissions change:
In my case, whenever a user logged in, the server responded with a set of permissions associated with that user. I wrote a <b>middleware</b> which on login-success read the permissions and updated the `redux-store`. I am also using redux-persist to save authorization and authentication information about the user in the local storage.

Now, <b>*when the permissions are changed for any user, the user’s authorization-token is expired*</b>. This is very important or the user-permissions won’t be updated in the redux-store and no change will be visible. The changes with the new permissions are reflected when the user logins again.

------------------------------

This approach of RBAC may not be what’s ideal, but this works for me. A few important steps I have skipped over, as they are subjective to an application, viz.,
* Agreeing on the structure of the permissions. In my case, I arranged the permissions `route-wise` , but you can use any other structure.
* The <b>redux-middleware</b> part. This basically takes the server-response and transforms that into the structure mentioned in the first point.

--------------------

This post is also availabe as a medium post and can be found here : {% medium https://medium.com/@perfectsudh/role-based-access-control-in-react-redux-apps-8454d4ca1a3b %}