Email and Password Authentication

Email/password authentication is probably the most popular method of authentication used today. It allows users to register and sign in to our application by providing their email address and a password.

The Firebase Authentication SDK offers auth methods to create, sign in, and manage users that use their email addresses and passwords to sign in to our application.

Enable email/password authentication

To use the email/password sign-in method in our Firebase project, we need to enable the sign-in method in the Firebase console.

  1. Head to our Firebase project dashboard. Click the dropdown menu on the sidebar to show all products.
  2. Click the “Build” option, and then click the “Authentication” option to open the Auth section and “Get started”.
  3. Click on the “Email/Password” option under the “Native providers” section of the “Sign-in method” page.
  4. Click the toggle button to enable email/password authentication and click “Save”.

Create users

There are two ways of creating users in a Firebase project:

  • Manually create password-authenticated users by clicking the “Add User” button on the “Authentication” section of our project dashboard.
  • Use the Firebase Authentication SDK to write functions that automatically create users on our application.

Sign up users with the Auth SDK

For a user to sign up on our application with their email address and password, we must pass the user’s credentials to the createUserWithEmailAndPassword function imported from the firebase/auth subpackage. This function creates a new user account in our Firebase project and sets the user’s initial password.

The createUserWithEmailAndPassword function takes three arguments. The first argument is the auth object that represents the initialized auth instance. Then, it takes the email and password values that we obtain from our client-side input fields. This function is asynchronous and takes some time to complete. Therefore, we can attach a JavaScript promise (Text in the key: The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.) that allows us to handle the function’s success value or failure reason.

The then method on the promise takes a callback function that runs when the action is complete. The callback function also takes the userCredential object as an argument.We can access certain information about the user who just signed up through this:

import { getAuth, createUserWithEmailAndPassword } from "firebase/auth";
const auth = getAuth(firebaseApp);
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed up
const user = userCredential.user;
// ...
})
.catch((err) => {
console.log(err.code);
console.log(err.message);
});

When a user signs up for our application, they are automatically signed in and a new user account is created under the Firebase project that links to their credentials. This user account identifies the user across all applications in the project, regardless of the sign-in method.

Sign in users

The steps for signing in a user with an email and password are similar to those for creating a new user with an email and password. To sign in a user with an email and password, we pass the user’s credentials to the signInWithEmailAndPassword function:

import { getAuth, signInWithEmailAndPassword } from "firebase/auth";
const auth = getAuth(firebaseApp);
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
// ...
})
.catch((err) => {
console.log(err.code);
console.log(err.message);
});

Handling errors

During the login or signup process, it is possible for users to input wrong data that might trigger errors that lead to unhandled exception situations. Therefore, we need to handle possible errors appropriately. Firebase offers a way to handle possible authentication errors regardless of the sign-in method. This list of errors exists on the AuthErrorCodes object, imported from the firebase/auth subpackage. Handling errors this way allows us to display better, user-readable error messages on our application:

import { AuthErrorCodes, createUserWithEmailAndPassword, getAuth } from "firebase/auth";
const auth = getAuth();
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed up
// ...
})
.catch((err) => {
if (err.code === AuthErrorCodes.WEAK_PASSWORD) {
alert("The password is too weak");
}
});

Check the Firebase documentation for a complete list of possible error codes.

Practice exercise

The highlighted lines in the widget below demonstrate how to create and sign in users in Firebase.

import { getAuth, signOut } from "firebase/auth";
import React from "react";
import logo from "../logo/Firebase.png";
import { firebaseApp } from "../services/firebase";

function Home() {
  const auth = getAuth(firebaseApp);

  var handleClick = () => {
    signOut(auth);
  };

  return (
    <div className="home">
      <p>Currently signed in as <strong>{auth.currentUser.email}</strong></p>
      <button title="signout" aria-label="signout" onClick={handleClick}>
        Signout
      </button>
      <div className="App-main">
        <img src={logo} className="App-logo" alt="logo" />
        Welcome to Firebase Auth <br />
      </div>
    </div>
  );
}

export default Home;
The email and password auth playground

Steps to perform

  • Study the highlighted lines in Login.jsx and Signup.jsx.
  • Open the output in a new tab after running the code. Use the given link to view the application better.