Skip to content
Related Articles

Related Articles

How to prevent access to admin pages using Node.js and React.js ?

View Discussion
Improve Article
Save Article
  • Last Updated : 28 Mar, 2022
View Discussion
Improve Article
Save Article

In many websites, the content available to the end-user is limited until he/she proves his/her authenticity by logging in. During the development of MERN Stack Applications, when the server is linked to the client, we may want to limit the pages accessed by the user unless he is logged in. In this article, let’s have a look at how to access admin pages is restricted using React.js and Node.js.

Pre-requisites:

Modules Required on the client-side:

  • axios
  • react-router-dom

Modules Required on the server-side:

  • express
  • cors

Client and Server setup: 

Step 1: Create an npm repository using the command:

npm init --y

Step 2: Create a new react client project by using the command:

npx create-react-app client

Step 3: Create a server file in the current directory using the command:

touch server.js

Step 4: Switch to the src folder in the client folder and remove all the files using the following command:

cd client
cd src
rm *

Step 5: Create a pages folder in the src folder

mkdir pages

Step 6: In the src folder create App.js, index.js, and PrivateRoute.js files.

touch App.js index.js PrivateRoute.js

Step 7: In the pages folder create Home.js Admin.js files.

cd pages
touch Home.js Admin.js

Step 8: Install Axios and react-router-dom in the client folder

npm i axios react-router-dom

Step 9: Install express and cors in the server-side

npm i express cors

Project Structure: The file structure in the project will look like this.

Project Structure

Step 10: Editing index.js to link the HTML file and react libraries.

Javascript




import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
 
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

Step 11: Editing Home.js to illustrate a basic Home Page

Javascript




const Home = () => {
    return(
        <div className="home">
            <h1>This is the Home page</h1>
        </div>
    )
}
 
export default Home;

Step 12: Editing Admin.js to illustrate a basic Admin Page

Javascript




const Admin = () => {
    return(
        <div>
            <h1>Admin Page</h1>
        </div>
    )
}
 
export default Admin;

Step 13: Creating a private route that prevents webpage access to unauthorized users. This route can be used for any component which needs to be protected. The private route essentially makes an API call to the server to check the user’s authenticity. If successfully authenticated, the route renders the supposed component else it redirects to the home page.

Javascript




// Importing the required libraries
import { Navigate } from "react-router-dom";
import { useEffect, useState } from "react";
const axios = require('axios');
 
 
// Private Route Component
// Params: login -> indicates the login state
//         children -> the child components of private route
const PrivateRoute = ({ login, children }) => {
 
  // Authentication Handler
  const authenticate = (login) => {
 
    setLoading(true);
 
    // HTTP Post Request
    axios({
      method: 'post',
      url: 'http://localhost:8000/admin',
      data: {
        logged: login,
      }
    }).then(({ data }) => {
      if(data.success){
        setAuth(true);
      }else{
        setAuth(false);
      }
      console.log(data.message);
      setLoading(false);
    }).catch((error) => {
      console.log(error);
      setLoading(false);
    })
  }
 
  // useState hook to inform the user about the loading state
  const [loading, setLoading] = useState(true);
 
  // useState hook to authorize the user
  const [auth, setAuth] = useState(false);
 
  // Authenticates the user whenever the
  // login state changes
  useEffect(() => {
    authenticate(login);
    return () => {
      setLoading(true);
    };
  }, [login])
 
  // If authenticated loads the required component
  // else redirects to the home page
  return loading ? (
    <h1>Loading...</h1>
  ) : auth ? children : (
    <Navigate to="/" />
  );
};
 
export default PrivateRoute;

Step 14: Integrating all the components in the App.js file. Routers are used to navigate between the home page and the admin page. We will create a button component to login and logout. Link tags are created for navigation purposes. Local Storage is used to sustain the login state between subsequent re-renders.

Javascript




// Importing the required modules
import { BrowserRouter as Router, Routes,
    Route, Link } from "react-router-dom";
import Home from "./pages/Home";
import Admin from "./pages/Admin";
import PrivateRoute from "./PrivateRoute";
import { useEffect, useState } from "react";
 
const App = () => {
   
  // useState hook to keep track of the login state
  const [login, setLogin] = useState(() => {
 
    // Used local storage to sustain the login state
    if(!localStorage.getItem("login")){
      localStorage.setItem("login", "false");
      return false;
    }
    return JSON.parse(localStorage.getItem("login"));
  });
 
  // Updating the local storage whenever
  // the login state changes
  useEffect(() => {
    localStorage.setItem("login", JSON.stringify(login));
  }, [login]);
 
  // Click Handler updates the login state
  // when the button is clicked
  const click = () => {
    setLogin((prev) => {
      return !prev;
    });
  }
 
  return (
    <div className="App">
      <Router>
        <button onClick={() => click()}>
          {login? "Logout" : "Login"}
        </button>
        <Link to={"/admin"}>Admin</Link>
        <Link to={"/"}>Home</Link>
        <Routes>
          <Route path="/" element={<Home />} />
          {/* Protecting the Admin Page */}
          <Route
            path="/admin"
            element={
            <PrivateRoute login={login}>
              <Admin />
            </PrivateRoute>
            }
          />
        </Routes>
      </Router>
    </div>
  );
}
 
export default App;

Step 15: Creating the server and listening to incoming requests on port 8000. We have created a middleware function to authenticate the user. This middleware function can be applied to any route.

Javascript




// Importing the required modules
const express = require('express');
const cors = require('cors');
 
// Creating an express server
const app = express();
 
// Middleware to parse the data into JSON
app.use(express.json())
 
// Middleware to accept requests from localhost:3000
app.use(
    cors({
      origin: "http://localhost:3000",
      credentials: true,
    })
);
 
// Middleware Function to authenticate the user
const auth = (req, res, next) => {
    console.log(req.body);
    if(req.body.logged){
        next();
        return;
    }
    res.send({
        success: false,
        message: "Unauthorized Access"
    });
}
 
// Post request handler for the /admin route
app.post("/admin", auth, (req, res) => {
    res.send({
        success: true,
        message: "Successfully Authenticated"
    });
})
 
app.listen(8000, () => {
    console.log("Listening on port 8000")
})

Steps to run the application:

Run the following command in the client folder

npm start

Run the following command in the base directory

node server.js

Output:

Basic Web App

If everything is working as intended, we should be seeing:

  • The following output on the server-side when we logout and login

Server-side output

  • The following output on the client-side when we logout and login

Client-side output

Final Output:

Final Output


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!