Firebase ile Kimlik Doğrulama

Melih ŞAHİN
Kodcular
Published in
6 min readFeb 11, 2024

Merhabalar,

Bugünkü yazımda Sizlere Next js projesinde, firebase kullanarak nasıl kimlik doğrulama (authentication) yapılır onu anlatacağım.

Öncelikle bu işlemi yapmadan google hesabımızla firebase’ e giriş yapıp proje oluşturmamız gerek. Sırayla bu adımları gerçekleştirelim.

https://firebase.google.com adresine giderek google hesabımızla giriş yapalım. Bizi aşağıdaki gibi bir ekran karşılayacak.

Create a project butonuna tıklayarak projemize isim vererek oluşturuyoruz.

Adımları tamamlayıp projeyi oluşturduğumuzda aşağıdaki gibi bir ekranla bize belirtiyor.

Console paneline geldiğimizde kırmızı okla gösterdiğim web kısmını seçerek web uygulamamızı kaydediyoruz ve firebase sdk’yini projemize ekleyeceğimiz bilgileri alıyoruz.

Localimizde next js projesi oluşturup daha sonra firebase paketini projemize dahil ediyoruz. Ekranda bize verdiği firebase config bilgilerini de environment dosyamıza ekleyerek buradan kullanacağız.

Yukarıdaki işlemi de tamamladıktan sonra, console ekranında yapacağımız son bir işlem kaldı. Authentication kısmına giderek “sign-in metod” tab’ ından kimlik doğrulama metodumuzu seçmemiz gerekiyor. Bu makalede e-posta ve parola ile kimlik doğrulama yapmak istediğimizden dolayı native providers kısmından “email/password” ‘ u seçiyoruz.

“email/password” alanını tıklayıp aktif hale getirmemiz gerekiyor. Daha sonra kaydedip console ile işlemlerimizi tamamlamış oluyoruz.

Şimdi next js projemize dönüp “giriş yap”, “kayıt ol” ve yalnızca giriş yapan kullanıcıların görebileceği koruma altındaki rotayı oluşturalım.

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;

signup.tsx


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

firebase servisini projemize entegre olmasını sağlayan kısım:

/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 () firebase de kayıtlı olan uygulamamızı bize döndüren fonksiyondur.

initializeApp () firebase ortam bilgilerimizi parametre alan fonksiyon, uygulama nesnesi oluşturmaya yarıyor.

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

getAuth () fonksiyonu oluşturduğumuz firebase uygulama nesnesine göre kimlik doğrulama sağlayacısını döndürüyor. (bizim uygulamamız da email/password olarak bu sağlayıcı seçmiştik)

signup.tsx

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

createUserWithEmailAndPassword() email ve parolaya göre firebase tarafında yeni kullanıcı oluşturmaya yarar.

updateProfile() oluşturulan kullanıcıya profil resimi, tam ismi gibi özellikler atamaya yarar.

react-firebase-hooks “ paketi kullanarak giriş yapan kullanıcı bilgilerine ulaşabiliriz.

login.tsx

const [user, loading] = useAuthState(auth);
giriş yap sayfası
kayıt ol sayfası
yalnızca kayıtlı kullanıcıların görebildiği sayfa

Örnek projenin kaynak kodlarına bu linkten ulaşabilirsiniz. 🔗

İçeriklere devam 🚀

Diğer içeriklerime bu linke tıklayıp ulaşabilirsiniz. Beğenip yorum bırakırsanız çok mutlu olurum 😇

--

--