DEV Community

Michael Burrows
Michael Burrows

Posted on • Updated on • Originally published at w3collective.com

React user registration & authentication using Firebase

In this tutorial we’ll be using the Firebase Authentication service to setup user registration and authentication in a React application. Firebase simplifies the process of user authentication allowing you to focus on other parts of the development process.

Completed source code can be found on GitHub.

Let’s get started by creating our application using Create React App and installing the Firebase and React Router dependencies by running the following commands:

npx create-react-app react-firebase-auth
cd react-firebase-auth
npm install firebase react-router-dom
Enter fullscreen mode Exit fullscreen mode

Setup Firebase

Create a Firebase account and add a “New Project”.

Follow the prompts to complete the setup and you’ll end up here:

Alt Text

Add Firebase to your app using the web option (</>).

To complete the Firebase setup we need to specify an authentication method. There are a number of methods available but for this tutorial we’ll be using the email and password method. Navigate to “Authentication” -> “Sign-in Method” and change the “Email/Password” status setting to “Enabled”.

Firebase config

Create a new file in the following location – src/config.js.

This file import’s the Firebase SDK and contains the Firebase configuration settings:

import firebase from "firebase/app";
import "firebase/auth";

const firebaseConfig = firebase.initializeApp({
  apiKey: "AIzaSyBRnU-ukg1hajloAXYxmU_2wiKnwbNKDhA",
  authDomain: "react-firebase-auth-6270e.firebaseapp.com",
  databaseURL: "https://react-firebase-auth-6270e.firebaseio.com",
  projectId: "react-firebase-auth-6270e",
  storageBucket: "react-firebase-auth-6270e.appspot.com",
  messagingSenderId: "83091629514",
  appId: "1:83091629514:web:99702034755a934a5a9b33",
});

export default firebaseConfig;
Enter fullscreen mode Exit fullscreen mode

Copy these setting from “Project Settings” -> “General” in the Firebase console.

Sign up form

Create a new file in the following location – src/components/SignUp.js.

This component contains a sign up form so users can create accounts:

import React, {useState} from "react";
import { Redirect } from "react-router-dom";
import firebaseConfig from "../config";

const SignUp = () => {
  const [currentUser, setCurrentUser] = useState(null);    
  const handleSubmit = (e) => {
    e.preventDefault();    
    const { email, password } = e.target.elements;
    try {
      firebaseConfig.auth().createUserWithEmailAndPassword(email.value, password.value);      
      setCurrentUser(true);
    } catch (error) {
      alert(error);
    }
  };
  if (currentUser) {
      return <Redirect to="/dashboard" />;
  }
  return (
    <>
      <h1>Sign Up</h1>
      <form onSubmit={handleSubmit}>
        <label for="email">Email</label>
        <input type="email" name="email" placeholder="Email" />
        <label for="password">Password</label>
        <input type="password" name="password" placeholder="Password" />
        <button type="submit">Submit</button>
      </form>
    </>
  );
};

export default SignUp;
Enter fullscreen mode Exit fullscreen mode

On form submit we’re passing the email & password entered to the Firebase Auth createUserWithEmailAndPassword method. If successful the browser will redirect to a dashboard page that contains content only visible to authenticated users. If the sign up fails and alert message describing the error is triggered.

Authentication

Create a new file in the following location – src/components/Auth.js.

This component determines whether or not a user has been authenticated:

import React, { useEffect, useState } from "react";
import firebaseConfig from "../config.js";

export const AuthContext = React.createContext();

export const AuthProvider = ({ children }) => {
  const [loading, setLoading] = useState(true);
  const [currentUser, setCurrentUser] = useState(null);
  useEffect(() => {
    firebaseConfig.auth().onAuthStateChanged((user) => {
      setCurrentUser(user);
      setLoading(false);
    });
  }, []);
  if (loading) {
    return <p>Loading...</p>;
  }
  return (
    <AuthContext.Provider value={{ currentUser }}>
      {children}
    </AuthContext.Provider>
  );
};
Enter fullscreen mode Exit fullscreen mode

Here we create a AuthContext object which is used to share the currentUser status between our various components. onAuthStateChanged is an observer for changes to the user’s sign-in state, this is triggered when user’s sign in or sign out.

Log in form

Create a new file in the following location – src/components/LogIn.js.

This component contains the log in form so users can sign into their account:

import React, { useContext } from "react";
import { Redirect } from "react-router-dom";
import { AuthContext } from "./Auth";
import firebaseConfig from "../config.js";

const LogIn = () => {
  const handleSubmit = (e) => {
    e.preventDefault();
    const { email, password } = e.target.elements;
    try {
      firebaseConfig.auth().signInWithEmailAndPassword(email.value, password.value);
    } catch (error) {
      alert(error);
    }
  };
  const { currentUser } = useContext(AuthContext);
  if (currentUser) {
    return <Redirect to="/dashboard" />;
  }
  return (
    <>
      <h1>Log In</h1>
      <form onSubmit={handleSubmit}>
        <label for="email">Email</label>
        <input type="email" name="email" placeholder="Email" />
        <label for="password">Password</label>
        <input type="password" name="password" placeholder="Password" />
        <button type="submit">Submit</button>
      </form>
    </>
  );
};

export default LogIn;
Enter fullscreen mode Exit fullscreen mode

If the current user is already logged in they’ll get redirected to the dashboard. Otherwise we capture the form input on submit and send the details to the Firebase Auth signInWithEmailAndPassword method.

Dashboard

Create a new file in the following location – src/components/Dashboard.js.

This component contains content that can only be viewed by authenticated users:

import React, { useContext } from "react";
import { Redirect } from "react-router-dom";
import { AuthContext } from "./Auth";
import firebaseConfig from "../config.js";

const Dashboard = () => {
  const { currentUser } = useContext(AuthContext);
  if (!currentUser) {
    return <Redirect to="/login" />;
  }
  return (
    <div>
      <h1>Welcome</h1>
      <p>This is the dashboard, if you can see this you're logged in.</p>
      <button onClick={() => firebaseConfig.auth().signOut()}>Sign out</button>
    </div>
  );
};

export default Dashboard;
Enter fullscreen mode Exit fullscreen mode

If this page is accessed by a non-authenticated user the browser will re-direct to the login page. If the user is authenticated we display the private content. We’ve also included a button so users can sign out of their account.

Home page

Create a new file in the following location – src/components/Home.js.

This component contains links to relevant pages based on the authentication status:

import React, { useContext } from "react";
import { Link } from "react-router-dom";
import { AuthContext } from "./Auth";

const Home = () => {
  const { currentUser } = useContext(AuthContext);
  return (
    <>
      <h1>Home</h1>
      {currentUser ? (
        <p>
          You are logged - <Link to="/dashboard">View Dashboard</Link>
        </p>
      ) : (
        <p>
          <Link to="/login">Log In</Link> or <Link to="/signup">Sign Up</Link> 
        </p>
      )}
    </>
  );
};

export default Home;
Enter fullscreen mode Exit fullscreen mode

At any location in the application we can check the status of currentUser and display different content based on this status. Here we’ve provided a link to the private dashboard for authenticated users and log in / sign up links for non-authenticated users.

Pulling it all together in App.js

Modify the App.js file to include the following:

import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Home from "./components/Home";
import Dashboard from "./components/Dashboard";
import LogIn from "./components/LogIn";
import SignUp from "./components/SignUp";
import { AuthProvider } from "./components/Auth";

const App = () => {
  return (
    <AuthProvider>
      <Router>
        <Switch>
          <Route exact path="/" component={Home} />
          <Route exact path="/dashboard" component={Dashboard} />
          <Route exact path="/login" component={LogIn} />
          <Route exact path="/signup" component={SignUp} />
        </Switch>
      </Router>
    </AuthProvider>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

You can now run npm start to start the application and test out the registration and authentication process. Once the sign up form has been submitted you can browse to “Authentication” -> “Users” in the Firebase console to confirm registration was successful and manage user accounts.

Alt Text

You now know how to authenticate users in your React applications using Firebase. If you would like to learn more about Firebase Authentication I’d suggest checking out the official guide.

Top comments (3)

Collapse
 
drewswaycool profile image
Drew McMurry

Typo in the dashboard section. Should say:

"Create a new file in the following location – src/components/Dashboard.js.

Collapse
 
michaelburrows profile image
Michael Burrows

Thanks, article updated.

Collapse
 
cjcoop22 profile image
CJCoop22

Hi I've tried to do this and copied exactly (apart from changing Redirect to Navigate because it gave me an error) and my local host shows just a blank screen. I don't know how to fix this