In the previous article, we discussed about the concepts of nested routes and dynamic routes. so, moving onto the next step, today we will be covering the concept of protected routes and authentication in react router. It is one of the important tool to protect your routes form unauthorized users. We will be using React Context custom hooks useAuth to create authentication.
What is Protected Routes?
In simple terms, Protected Routes are basically the routes that are protected from the unauthorized access. We can access the protected routes only when certain conditions are fulfilled. Protected routes can also be referred to as the private routes. One of the examples of protected routes is admin dashboard. we cannot provide access to anyone for the admin dashboard. only the one with admin credentials should be able to access the admin dashboard. so to protect the /admin
route, we use protected routes. and to check if the user is admin or not we can use authentication to recognize a user’s identity.
Lets start with a tutorial on how to setup a protected route for admin dashboard. In this tutorial, we will protect a admin page route from the users that are not logged in.
Prerequisites
- Knowledge of react router.
How to Implement Protected Routes in React ?
Let’s have a step by step look on how to implement protected routes in react router along with authentication attached.
Step 1: Install required dependencies.
npm install react-router-dom
Step 2: Create a admin dashboard page.
Admin.js
import React from "react";
function Admin() {
return (
<div>
<h1>This is a protected page. Only admin can access this page.</h1>>
</div>
);
}
export default Admin;
Step 3: Create a custom hook useAuth that will be used to identify a user’s identity.
useAuth.js
import React, { createContext, useContext, useState } from "react";
import {useNavigate } from "react-router-dom";
const authContext = createContext();
export function AuthProvider({ children }) {
const [user, setUser] = useState({});
const navigate = useNavigate();
const login = (userDetails) => {
setUser(userDetails);
navigate("/admin/dashboard");
};
const logout = () => {
setUser({});
navigate("/");
};
return (
<authContext.Provider value={{ user, login, logout }}>
{children}
</authContext.Provider>
);
}
export const useAuth = () => {
return useContext(authContext);
};
Step 4: Create a RequireAuth function that checks the condition and decides whether or not to provide access to the user.
Here, we will check if a user has provided email or not to ensure that the user is logged in. If a unauthorized user tries to access admin route without logging in then it will be navigated to the login page /
route
RequireAuth,js
import React from "react";
import { useAuth } from "./useAuth";
import { Navigate } from "react-router-dom";
export const RequireAuth = ({ children }) => {
const auth = useAuth();
return auth.email ? (
children
) : (
<Navigate to="/"/>
);
};
We need to create a login page so that user can provide their identify and we can use that identify to check that identity.
Step 5: Create a login page.
Login.js
import React, { useState } from "react";
import { useAuth } from "./useAuth";
function Login() {
const auth = useAuth();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleLogin = () => {
auth.login({ email: email, password: password });
};
return (
<div>
<h1>Login Page</h1>
<span>Email</span>
<input
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<span>Password</span>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit" onClick={handleLogin}>
Log in
</button>
</div>
);
}
export default Login;
Here, we took the values of email and password entered by the user and passed it to the login function of useAuth. Now, we can access user’s identity from auth.user.
Step 6: Edit App.js.
App.js
import React from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Login from "./Login";
import { RequireAuth } from "./auth/RequireAuth";
import { AuthProvider } from "./auth/useAuth";
import Admin from "./admin";
function App() {
return (
<div>
<BrowserRouter>
<AuthProvider>
<Routes>
<Route path="/login" element={<Login />} />
<Route
path="/admin/dashboard"
element={
<RequireAuth>
<Admin />
</RequireAuth>
}
></Route>
</Routes>
</AuthProvider>
</BrowserRouter>
</div>
);
}
export default App;
Here, we enclosed the Routes component inside the AuthProvider
component. And to protect the admin page we enclosed it inside RequireAuth
so only if a user is logged in it can access the /admin/dashboard
route.
Conclusion
In this article, we discussed on how to protect a route in react using protected routes. We used the concepts of react-context , custom hooks to create a useAuth() hook. In the tutorial, we protected the admin route from the unauthorized users that are not logged in.