Home > OS >  Protected routes in React using firebase
Protected routes in React using firebase

Time:12-22

`` I am using firebase authentication to sign in users and then storing roles information in the real time database. If an user with admin role logs in to the site then they should be able to access the "/home" route but I am not able to do so.

App.js

import "./App.css";

import React from "react";
import { Route, Routes, Navigate } from "react-router-dom";

import Landing from "./components/Landing";
import PhoneDetails from "./components/PhoneDetails";
import Home from "./components/Home/App.jsx";
import Signup from "./components/Signup";
import SignIn from "./components/Signin";
import ForgotPassword from "./components/ForgotPassword";

import { auth } from "./firebase-config.js";
import { useEffect } from "react";
import FirebaseData from "./firebaseData";

function App() {
  document.body.style = "background: #F8F5FA;";

  // getting the user data from firebase
  const firebaseData = FirebaseData();

  const [displayName, setDisplayName] = React.useState("");
  const [isAuthenticated, setIsAuthenticated] = React.useState(false);
  const [role, setRole] = React.useState("");

  useEffect(() => {
    if (firebaseData) {
      auth.onAuthStateChanged((user) => {
        if (user) {
          // User is signed in
          // ...
          setIsAuthenticated(true);
          setDisplayName(user.displayName);
          setRole(firebaseData.users?.[user.uid]?.role);
        } else {
          // User is signed out
          // ...
          setIsAuthenticated(false);
          setDisplayName("");
          setRole("");
        }
      });
    }
  }, [firebaseData]);

  console.log("isAuthenticated:", isAuthenticated);
  console.log("displayName:", displayName);
  console.log("role:", role);

  return (
    <Routes>
      <Route
        path="/"
        exact
        element={
          <Home
            isAuthenticated={isAuthenticated}
            displayName={displayName}
            role={role}
          />
        }
      />
      <Route path="/signup" element={<Signup />} />
      <Route path="/signin" element={<SignIn />} />
      <Route path="/forgot-password" element={<ForgotPassword />} />

      <Route
        path="/home"
        element={
          isAuthenticated && role === "admin" ? (
            <Landing />
          ) : (
            <Navigate replace to="/" />
          )
        }
      />

      <Route
        path="/details"
        element={
          isAuthenticated && role === "admin" ? (
            <PhoneDetails />
          ) : (
            <Navigate replace to="/" />
          )
        }
      />
      <Route path="/" element={<Navigate replace to="/" />} />
    </Routes>
  );
}

export default App;

Given below is the real time data file I am fetching

firebaseData.js

import {database} from "./firebase-config";
import React from "react";
import {ref, onValue} from "firebase/database";
import {useEffect} from "react";

const db = database;

export default function FirebaseData() {
    const [data, setData] = React.useState(null);

    useEffect(() => {
        onValue(ref(db), (snapshot) => {
            setData(snapshot.val());
        });
    }, []);
    return data;

}

I am checking for authentication status and I am getting the role in the console log, but when I route to /home I am redirected to / route. I understand that I am not immediately getting the data from the DB because of useEffect hook, how to I fix this issue?

CodePudding user response:

I Assume role='admin' when user is admin ,then you can do it like this

 <Routes>
  <Route
    path="/"
    exact
    element={
      <Home
        isAuthenticated={isAuthenticated}
        displayName={displayName}
        role={role}
      />
    }
  />
  <Route path="/signup" element={<Signup />} />
  <Route path="/signin" element={<SignIn />} />
  <Route path="/forgot-password" element={<ForgotPassword />} />
    {
     role==='admin' && <Route
    path="/home"
    element={
      isAuthenticated && role === "admin" ? (
        <Landing />
      ) : (
        <Navigate replace to="/" />
      )
    }
  />
 }
  
  <Route
    path="/details"
    element={
      isAuthenticated && role === "admin" ? (
        <PhoneDetails />
      ) : (
        <Navigate replace to="/" />
      )
    }
  />
  <Route path="/" element={<Navigate replace to="/" />} />
</Routes>

For role other than admin it will fall to default route.

  • Related