Featured

Authentication with Firebase

Published on
4 read
Authentication with Firebase

 

Hello there

In today's article, I will tell you how to authenticate using firebase in the Next js project.

First of all, without doing this process, we need to log in to firebase with our google account and create a project. Let's perform these steps in order.

Let's go to https://firebase.google.com and log in with our google account. A screen like the one below will greet us.

Image description

By clicking on the Create a project button, we create our project by naming it.

Image description

When we complete the steps and create the project, it shows us a screen like the one below.

Image description

When we come to the console panel, we save our web application by selecting the web section I show with the red arrow and get the information to add the firebase sdk to our project.

Image description

Image description

Image description

We create a next js project in our local and then include the firebase package in our project. We will use the firebase config information it gives us on the screen by adding it to our environment file.

After completing the above process, we have one last action to do on the console screen. We need to go to the Authentication section and select our authentication method from the "sign-in method" tab. Since we want to authenticate with email and password in this article, we select "email/password" from the native providers section.

Image description

We need to click on the "email/password" field and activate it. Then we save and complete our operations with the console.

Image description

Now let's go back to our next js project and create the protected route that only logged in users can see.

login.tsx

"use client";
import * as Yup from "yup";
import Link from "next/link";
import { useFormik } from "formik";
import { redirect } from "next/navigation";
import toast, { Toaster } from "react-hot-toast";
import { Button } from "@nextui-org/react";
import EmailInput from "@/components/emailInput/EmailInput";
import PasswordInput from "@/components/passwordInput/PasswordInput";
import { useAuthState } from "react-firebase-hooks/auth";
import { signInWithEmailAndPassword } from "firebase/auth";

import { auth } from "@/lib/firebaseConfig";

const Login = () => {
  const [user, loading] = useAuthState(auth);

  const validationSchema = Yup.object().shape({
    email: Yup.string()
      .email("invalid or incomplete email")
      .max(50, "email is too long")
      .required("required"),
    password: Yup.string()
      .min(6, "password is too short must be at least 6 characters")
      .required("required"),
  });

  const formik = useFormik({
    initialValues: {
      email: "",
      password: "",
    },
    validationSchema,
    onSubmit: async ({
      email,
      password,
    }: {
      email: string;
      password: string;
    }) => {
      const res = await signInWithEmailAndPassword(auth, email, password);
      if (res?.user) {
        sessionStorage.setItem("user", "true");
        redirect("/");
      } else {
        toast.error("Check your user information!");
      }
    },
  });

  const { errors, values, touched, handleSubmit, handleChange, isSubmitting } =
    formik;

  if (typeof window !== "undefined") {
    if (user && sessionStorage.getItem("user")) return redirect("/");
  }

  if (loading) return <p>Checking...</p>;

  return (
    <div className="flex min-h-screen items-center justify-center bg-black">
      <div className="flex w-full max-w-md flex-col rounded-lg bg-white p-8 shadow-md">
        <div className="text-black-1 mb-12 flex flex-col items-center justify-center gap-y-3">
          <p className="text-2xl font-bold">Example App</p>
        </div>
        <form
          noValidate
          onSubmit={handleSubmit}
          className="flex flex-col gap-y-6"
        >
          <Toaster position="top-right" />
          <EmailInput
            handleChange={handleChange}
            values={values}
            errors={errors}
            touched={touched}
          />
          <PasswordInput
            handleChange={handleChange}
            values={values}
            errors={errors}
            touched={touched}
          />
          <Button
            fullWidth={true}
            type="submit"
            color="success"
            className="bg-primary rounded-lg px-6 py-3.5 text-lg text-white hover:bg-blue-600"
            isLoading={isSubmitting}
          >
            Login
          </Button>
        </form>
        <p className="mt-4 text-center text-sm text-gray-600">
          <Link href="/signup" className="text-blue-500">
            Sign up
          </Link>
        </p>
      </div>
    </div>
  );
};

export default Login;

The part that integrates the firebase service into our project:

/lib/firebaseConfig.ts

import { getApp, getApps, initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";

const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};

const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();

const auth = getAuth(app);

export { app, auth };

getApp() is the function that returns us our application registered in firebase.

initializeApp() is a function that takes our firebase environment information as a parameter to create an application object.
 
const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();

getAuth() function returns the authentication provider according to the firebase application object we created (in our application we chose this provider as email/password)

signup.tsx

const res = await createUserWithEmailAndPassword(auth, email, password);

createUserWithEmailAndPassword() is used to create a new user on firebase side according to email and password.

updateProfile() is used to assign properties such as profile picture, full name to the created user.

Image description

Using the "react-firebase-hooks" package, we can access the logged in user information.

login.tsx

const [user, loading] = useAuthState(auth);

Image description

Image description

Image description

You can access the source codes of the sample project from this link. 🔗

 

 

Discussion (0)

Subscribe