Implementing Role-Based Authentication with Firebase in Your App

Tuesday, January 28, 2025

Managing user roles is crucial for many applications, especially when you need to control who can access specific features or sections of your app. In this guide, we'll walk through implementing role-based authentication using Firebase Authentication and Firestore. Whether you're building an admin dashboard or a multi-user platform, this method ensures secure and scalable role management.


Step 1: Set Up Firebase Authentication

Before we can assign and manage roles, we need Firebase Authentication up and running in our app.

Initialize Firebase

  • Create a Firebase project in the Firebase Console.
  • Add your web app to the project and copy the Firebase config object.
  • Install the Firebase SDK in your project:
  • Initialize Firebase in your app:
  • Enable Authentication

  • Go to the Firebase Console, navigate to "Authentication," and enable the desired sign-in methods (e.g., Email/Password).
  • Create test user accounts (e.g., admin@example.com, editor@example.com).

  • Step 2: Add Role Information to Firestore

    Firestore will act as our database to store role-related information.

    Set Up a Firestore Collection

  • Create a collection named users or roles.
  • Each document should correspond to a user, with fields to define their role and permissions. Example structure:
  • Assign Roles to Users

  • When creating a new user, add their role to Firestore. Example code to save role during user registration:
  • Language: javascript
    import { doc, setDoc } from "firebase/firestore";
    import { getFirestore } from "firebase/firestore";
    
    const db = getFirestore(app);
    
    const createUserWithRole = async (userId, role) => {
      await setDoc(doc(db, "users", userId), {
        role: role,
        permissions: role === "admin" ? ["read", "write", "delete"] : ["read"],
      });
    };

    Step 3: Retrieve Role Data in Your App

    Once a user logs in, fetch their role from Firestore.

    Set Up an Auth Listener

    Use Firebase's onAuthStateChanged to detect when a user logs in:

    Language: javascript
    import { onAuthStateChanged } from "firebase/auth";
    import { doc, getDoc } from "firebase/firestore";
    
    onAuthStateChanged(auth, async (user) => {
      if (user) {
        const userDoc = await getDoc(doc(db, "users", user.uid));
        if (userDoc.exists()) {
          const role = userDoc.data().role;
          console.log("User role:", role);
        }
      }
    });

    Store the Role in State

    Use React Context or Redux to manage user roles globally:

    Language: javascript
    const [userRole, setUserRole] = useState("");
    
    useEffect(() => {
      if (user) {
        const fetchRole = async () => {
          const userDoc = await getDoc(doc(db, "users", user.uid));
          setUserRole(userDoc.data().role);
        };
        fetchRole();
      }
    }, [user]);

    Step 4: Enforce Role-Based Access in the Frontend

    Conditional Rendering

    Show or hide components based on the user's role.

    Example:

    Language: javascript
    if (userRole === "admin") {
      return <AdminDashboard />;
    } else {
      return <Unauthorized />;
    }

    Restrict Routes

    Use middleware to protect routes. Example with Next.js:

    Language: javascript
    export default function AdminPage({ userRole }) {
      if (userRole !== "admin") {
        return <p>Unauthorized</p>;
      }
      return <AdminDashboard />;
    }

    Step 5: Secure Data with Firestore Rules

    To ensure your database is secure, write Firestore rules that enforce role-based access.

    Example rule to restrict access to admins:

    Language: javascript
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /users/{userId} {
          allow read, write: if request.auth.uid == userId && resource.data.role == "admin";
        }
      }
    }

    Step 6: Testing and Debugging

  • Test users with different roles to ensure permissions are correctly applied.
  • Use Firebase's Firestore Rules simulator to verify access logic.

  • Conclusion

    Role-based authentication is an essential feature for any multi-user application. By leveraging Firebase Authentication and Firestore, you can manage roles securely and efficiently. Start implementing role-based authentication in your app today and scale your permissions model as your user base grows!