React - Role Based Authorization Tutorial with Example
Tags: react, abotwrotethis, webdev, javascript
Published: 2023-04-21 06:12:03

Have you ever been in a situation where you wanted to control the access to certain components or routes in your React project based on user roles? This is where role-based authorization comes into play. In this tutorial, we will walk you through the process of implementing role-based authorization in your React application with an example.

## What is Role-Based Authorization?

Role-based authorization is a security model that enables access control to resources based on the roles assigned to users. In simple terms, users with different roles will have different levels of access to resources such as components or routes in an application.

For example, in an e-commerce application, a customer with a guest role may only have access to the homepage and product listing page. On the other hand, an admin with an admin role may have access to the dashboard and the ability to add, edit, or delete products.

## Setting up the Project

Before we dive into the implementation, let's set up a new React project using Create React App. To do this, run the following command in your terminal:

```bash
npx create-react-app react-role-based-auth
```

Once the project is created, navigate to the project directory by running the following command in your terminal:

```bash
cd react-role-based-auth
```

## Creating User Roles

In this example, we will create two user roles - admin and guest. Create a new file called `roles.js` in the `src` directory and add the following code:

```javascript
export const ROLES = {
  ADMIN: "admin",
  GUEST: "guest"
}
```

In this code, we are creating two constants `ADMIN` and `GUEST` which represent the roles for our users.

## Creating the Routes

Next, let's create some routes for our application. We will create three routes - homepage, dashboard, and products. Create a new file called `Routes.js` in the `src` directory and add the following code:

```javascript
import React from "react";
import { Route, Redirect } from "react-router-dom";
import { ROLES } from "./roles";

export const PrivateRoute = ({ component: Component, role, ...rest }) => (
  <Route
    {...rest}
    render={(props) =>
      localStorage.getItem("auth-token") && role === ROLES.ADMIN ? (
        <Component {...props} />
      ) : (
        <Redirect to={{ pathname: "/", state: { from: props.location } }} />
      )
    }
  />
);

export const PublicRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={(props) => <Component {...props} />} />
);
```

In this code, we are creating two components - `PrivateRoute` and `PublicRoute`. The `PrivateRoute` component is used to protect routes that require authentication and only allow users with the admin role to access them. The `PublicRoute` component is used for routes that do not require authentication.

## Implementing the Authentication

To simulate authentication, we will create a simple login form. Create a new file called `LoginPage.js` in the `src` directory and add the following code:

```javascript
import React, { useState } from "react";

const LoginPage = ({ setUser }) => {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");

  const handleLogin = () => {
    // Simulating authentication
    if (username === "admin" && password === "admin") {
      localStorage.setItem("auth-token", "admin-token");
      setUser({ role: "admin" });
    } else if (username === "guest" && password === "guest") {
      localStorage.setItem("auth-token", "guest-token");
      setUser({ role: "guest" });
    }
  };

  return (
    <div>
      <h2>Login Page</h2>
      <div>
        <label>
          Username:
          <input
            type="text"
            value={username}
            onChange={(e) => setUsername(e.target.value)}
          />
        </label>
      </div>
      <div>
        <label>
          Password:
          <input
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          />
        </label>
      </div>
      <div>
        <button onClick={handleLogin}>Login</button>
      </div>
    </div>
  );
};

export default LoginPage;
```

In this code, we are creating a simple login form with username and password fields. We are also simulating authentication by storing the user's role in local storage.

## Displaying the User Role

To display the user's role, we will create a new component called `ProfilePage`. Create a new file called `ProfilePage.js` in the `src` directory and add the following code:

```javascript
import React from "react";

const ProfilePage = ({ role }) => {
  return (
    <div>
      <h2>Profile Page</h2>
      <p>You are logged in as: {role}</p>
    </div>
  );
};

export default ProfilePage;
```

In this code, we are simply displaying the user's role.

## Implementing the Routes

Now that we have our authentication and routes set up, let's implement them in our application. Open the `App.js` file and replace the default code with the following:

```javascript
import React, { useState } from "react";
import { BrowserRouter, Switch } from "react-router-dom";
import { PrivateRoute, PublicRoute } from "./Routes";
import { ROLES } from "./roles";
import LoginPage from "./LoginPage";
import ProfilePage from "./ProfilePage";

const App = () => {
  const [user, setUser] = useState({});

  return (
    <BrowserRouter>
      <Switch>
        <PublicRoute exact path="/" component={LoginPage} />
        <PrivateRoute
          path="/dashboard"
          component={() => (
            <ProfilePage role={user.role} />
          )}
          role={ROLES.ADMIN}
        />
        <PublicRoute
          path="/products"
          component={() => (
            <ProfilePage role={user.role} />
          )}
        />
      </Switch>
    </BrowserRouter>
  );
};

export default App;
```

In this code, we are using the `BrowserRouter` and `Switch` components from `react-router-dom` to define our routes. We are also using the `PrivateRoute` and `PublicRoute` components to protect our routes.

The `PrivateRoute` component is used for the `/dashboard` route, which requires authentication and only allows users with the admin role to access it. The `PublicRoute` component is used for the `/products` route, which does not require authentication.

## Testing the Application

To test the application, run the following command in your terminal:

```bash
npm start
```

This will start the development server and open your default browser. You should see the login page.

Enter `admin` as the username and `admin` as the password. This will log you in as an admin user and redirect you to the dashboard page.

Enter `guest` as the username and `guest` as the password. This will log you in as a guest user and redirect you to the products page.

If you try to access the dashboard page as a guest user, you will be redirected back to the login page.

## Conclusion

In this tutorial, we walked you through the process of implementing role-based authorization in your React application. We created two user roles, created routes, implemented authentication, and tested the application.

Role-based authorization is an important security feature in any application, and it can be easily implemented in your React project using the techniques we've covered in this tutorial.