Authentication with Firebase
Tags: firebase, authentication, nextjs, javascript
Published: 2024-02-12 07:47:43

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](https://firebase.google.com) and log in with our google account. A screen like the one below will greet us.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1egx1v28vdvnvn7nc97i.png)

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


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n99jhp0z7vb3xoip8gqm.png)

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


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nrtnbl00pd7nbvrzby54.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4gx433kn351yvgvzp0f.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8eti6f1og0quiicm3tm3.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dtkohq1zkd98fl6igrky.png)

> 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5itjcb14sjsqki10ujzr.png)

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ft1lavo1n2v7z052svc.png)

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

**login.tsx**

```typescript
"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;

```
**signup.tsx**

```typescript
"use client";
import * as Yup from "yup";
import Link from "next/link";
import { useFormik } from "formik";
import { redirect } from "next/navigation";
import { auth } from "@/lib/firebaseConfig";
import { updateProfile } from "firebase/auth";
import toast, { Toaster } from "react-hot-toast";
import { Button, Input } from "@nextui-org/react";
import { useAuthState } from "react-firebase-hooks/auth";
import { createUserWithEmailAndPassword } from "@firebase/auth";

import EmailInput from "@/components/emailInput/EmailInput";
import PasswordInput from "@/components/passwordInput/PasswordInput";

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

  const validationSchema = Yup.object().shape({
    fullName: Yup.string().required("required"),
    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: "",
      fullName: "",
      password: "",
    },
    validationSchema,
    onSubmit: async ({
      email,
      password,
      fullName,
    }: {
      email: string;
      password: string;
      fullName: string;
    }) => {
      const res = await createUserWithEmailAndPassword(auth, email, password);
      await updateProfile(auth?.currentUser as any, {
        displayName: fullName,
        photoURL: "https://i.pravatar.cc/150?u=a04258114e29026302d",
      });

      res?.user ? sessionStorage.setItem("user", "true") : toast.error("error");
    },
  });

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

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

  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" />
          <div>
            <Input
              size="lg"
              type="text"
              label="User name"
              name="fullName"
              labelPlacement="outside"
              placeholder="Enter your name"
              onChange={handleChange}
              value={values?.fullName}
              errorMessage={errors?.fullName}
              isInvalid={(errors?.fullName && touched?.fullName) as boolean}
            />
          </div>
          <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="green-1 rounded-lg px-6 py-3.5 text-lg text-white hover:bg-green-600"
            isLoading={isSubmitting}
          >
            Sign up
          </Button>
        </form>
        <p className="mt-4 text-center text-sm text-gray-600">
          <Link href="/login" className="text-blue-500">
            Sign in
          </Link>
        </p>
      </div>
    </div>
  );
};

export default Signup;
```

The part that integrates the firebase service into our project:

**/lib/firebaseConfig.ts**

```typescript
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.

```typescript
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**

```typescript
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/53utbvozha0jy7qvfd6l.png)

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

**login.tsx**

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eqq7t61951jyjro2q5x3.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqrn3gbvle01lsdhz5sx.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ke4kpbzmbedzgbwu01u.png)

You can access the source codes of the sample project from **[this link](https://github.com/melihs/example-firebase-authentication)**. 🔗

## Continue with content 🚀
You can access my other content by clicking **[this link](https://medium.com/@melihsahin)**. I would be very happy if you like and leave a comment 😇