Firebase est une plateforme complète de développement mobile et web, proposée par Google, qui fournit une suite de services, notamment des outils pour gérer des bases de données en temps réel, l’authentification, l’hébergement, le stockage, et bien plus encore. Parmi ses modules les plus populaires, on retrouve le service d’authentification, qui permet de gérer facilement la création, la connexion et la gestion des utilisateurs avec divers fournisseurs (email, Google, Facebook, etc.).
Ainsi, Firebase Authentication simplifie le processus de gestion des utilisateurs et garantit une sécurité fiable en s’intégrant sans difficulté dans les applications grâce aux SDK pour plusieurs langages et plateformes. Nous allons donc explorer comment configurer Firebase Authentication dans une application Next.js, avec des exemples de code pratiques pour gérer l’inscription, la connexion, la déconnexion, ainsi que l’authentification avec Google.
Sommaire
- Installation et configuration de Firebase
- Création d’un hook personnalisé pour l’authentification
- Mise en place des fonctionnalités d’inscription, de connexion et de connexion via Google
- Intégration du composant de connexion et d’inscription
- Création de la page Dashboard et gestion de la déconnexion
- Conclusion
1. Installation et configuration de Firebase
Pour intégrer Firebase Authentication dans une application Next.js, nous devons d’abord configurer Firebase et ajouter les dépendances nécessaires.
Étape 1 : Créer un projet Firebase
D’abord, rendez-vous sur la console Firebase et créez un nouveau projet. Ensuite, ajoutez une application web dans votre projet. Vous obtiendrez alors les informations de configuration nécessaires, telles que l’API Key et le Auth Domain.
Étape 2 : Installer les dépendances Firebase
Ensuite, dans votre projet, installez Firebase avec la commande suivante :
npm install firebase
Étape 3 : Configurer Firebase dans votre projet
Pour continuer, créez un fichier firebaseConfig.js
dans votre dossier db
et configurez Firebase comme suit :
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
// Configuration Firebase - remplacez les placeholders par vos propres valeurs
const firebaseConfig = {
apiKey: "<VOTRE_API_KEY>",
authDomain: "<VOTRE_AUTH_DOMAIN>",
projectId: "<VOTRE_PROJECT_ID>",
storageBucket: "<VOTRE_STORAGE_BUCKET>",
messagingSenderId: "<VOTRE_MESSAGING_SENDER_ID>",
appId: "<VOTRE_APP_ID>",
};
// Initialisation de Firebase
export const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
2. Création d’un hook personnalisé pour l’authentification
À ce stade, nous allons créer un hook personnalisé, useClientAuth
, pour centraliser les fonctions d’authentification, telles que l’inscription, la connexion, et la connexion via Google.
Code du hook useClientAuth
import { useState, useEffect } from "react";
import { createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, User, GoogleAuthProvider, signInWithPopup } from "firebase/auth";
import { auth } from "../db/firebaseConfig";
import { useRouter } from "next/navigation";
const provider = new GoogleAuthProvider();
const useClientAuth = () => {
const [user, setUser] = useState<User | null>(null);
const [isFetch, setIsFetch] = useState(true);
const router = useRouter();
const signUp = async (email: string, password: string) => {
try {
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
setUser(userCredential.user);
router.push("/dashboard");
} catch (error) {
console.error("Erreur lors de l'inscription :", error);
}
};
const signIn = async (email: string, password: string) => {
try {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
setUser(userCredential.user);
router.push("/dashboard");
} catch (error) {
console.error("Erreur lors de la connexion :", error);
}
};
const loginWithGoogle = async () => {
try {
const result = await signInWithPopup(auth, provider);
setUser(result.user);
router.push("/dashboard");
} catch (error) {
console.error("Erreur lors de la connexion Google :", error);
}
};
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setUser(user);
setIsFetch(false);
});
return () => unsubscribe();
}, []);
return { user, isFetch, signUp, signIn, loginWithGoogle };
};
export default useClientAuth;
3. Mise en place des fonctionnalités d’inscription, de connexion et de connexion via Google
Grâce à notre hook useClientAuth
, nous disposons maintenant des fonctionnalités de base de Firebase Authentication. Nous allons maintenant les intégrer dans un composant de connexion et d’inscription.
4. Intégration du composant de connexion et d’inscription
Nous pouvons maintenant créer une page de connexion et d’inscription, PageSignInAndUp
, qui permet à l’utilisateur de basculer facilement entre les deux options. De plus, nous intégrerons une validation de formulaire avec Yup pour une expérience utilisateur améliorée.
import { useState, ChangeEvent } from 'react';
import * as Yup from 'yup';
import useClientAuth from '../../hooks/useClientAuth';
import GoogleLogo from "../../../public/logo-google.webp";
import Image from "next/image";
interface FormData {
email: string;
password: string;
}
const schema = Yup.object().shape({
email: Yup.string().email('Format Mail invalide').required('Email requis'),
password: Yup.string().required('Mot de passe requis')
});
export default function PageSignInAndUp() {
const [isSignUpActive, setIsSignUpActive] = useState(false);
const { isFetch, signUp, signIn, loginWithGoogle } = useClientAuth();
const [formData, setFormData] = useState<FormData>({ email: '', password: '' });
const [errors, setErrors] = useState<Partial<FormData>>({});
const handleFormChange = () => {
setIsSignUpActive(!isSignUpActive);
setFormData({ email: '', password: '' });
setErrors({});
};
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
setFormData((prevData) => ({
...prevData,
[name]: value
}));
};
const handleSubmit = () => {
schema.validate(formData, { abortEarly: false })
.then(() => {
isSignUpActive ? signUp(formData.email, formData.password) : signIn(formData.email, formData.password);
})
.catch((validationErrors) => {
const formattedErrors: Partial<FormData> = {};
validationErrors.inner.forEach((error) => {
formattedErrors[error.path as keyof FormData] = error.message;
});
setErrors(formattedErrors);
});
};
if (isFetch) {
return <h2>En cours de connexion...</h2>;
}
return (
<section className="w-full h-screen flex items-center justify-center flex-col gap-2 ">
<form className="max-w-[800px] flex flex-col gap-2 bg-slate-50 p-5 rounded shadow-md">
{isSignUpActive ? (
<h1 className="text-center text-gray-900 text-4xl mb-3 font-bold">Inscription</h1>
) : (
<h1 className="text-center text-gray-900 text-4xl mb-3 font-bold">Connexion</h1>
)}
<label className="text-slate-900">Email</label>
<input
type="email"
onChange={handleInputChange}
value={formData.email}
name="email"
className="h-10 border border-slate-900 rounded p-4"
/>
{errors.email && <p className="text-red-500">{errors.email}</p>}
<label className="text-slate-900">Password</label>
<input
type="password"
onChange={handleInputChange}
value={formData.password}
name="password"
className="h-10 border border-slate-900 rounded p-4"
/>
{errors.password && <p className="text-red-500">{errors.password}</p>}
{isSignUpActive ? (
<button
onClick={handleSignUp}
type="button"
className="bg-gray-600 px-3 py-1.5 text-white my-3 rounded hover:bg-gray-700"
>
S'inscrire
</button>
) : (
<button
onClick={handleSignIn}
type="button"
className="bg-gray-600 px-3 py-1.5 text-white my-3 rounded hover:bg-gray-700"
>
Se connecter
</button>
)}
{isSignUpActive ? (
<a onClick={handleFormChange} href="#" className="text-red-500 hover:text-red-900">
Déja un compte? Se connecter
</a>
) : (
<a onClick={handleFormChange} href="#" className="text-red-500 hover:text-red-900">
Pas de compte? Créer un compte
</a>
)}
</form>
<button
onClick={loginWithGoogle}
type="button"
className=" bg-gray-200 hover:bg-gray-300 rounded-md text-gray-800 p-2 flex items-center gap-2"
>
<Image src={GoogleLogo} width={30} height={30} alt="Logo Google" />
<span>{isSignUpActive ? "Inscription via Google" : "Connexion via Google"}</span>
</button>
</section>
);
}
5. Création de la page Dashboard et gestion de la déconnexion
Le Dashboard
représente une page réservée aux utilisateurs authentifiés. En outre, cette page permet également à l’utilisateur de se déconnecter de l’application.
Code de la page Dashboard
import { signOut } from "firebase/auth";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
import { auth } from "../../db/firebaseConfig";
import useClientAuth from '../../hooks/useClientAuth';
export default function PageDashboard() {
const { user } = useClientAuth();
const router = useRouter();
const handleSignOut = () => {
signOut(auth)
.then(() => {
console.log("Déconnexion réussie");
router.push('/');
})
.catch((error) => console.error("Erreur de déconnexion :", error));
};
return (
<div className="h-screen w-full flex items-center justify-center flex-col">
<h1 className="text-4xl uppercase font-black">Dashboard</h1>
<p><b>Votre email : </b>{user?.email}</p>
<button onClick={handleSignOut} className="mt-5">Déconnexion</button>
</div>
);
}
6. Conclusion
En suivant les étapes précédentes, vous avez mis en place un système d’authentification complet dans une application Next.js, incluant les fonctionnalités d’inscription, de connexion et d’authentification via Google. Pour approfondir vos connaissances en Next JS et maîtriser ces nouvelles fonctionnalités, n’hésitez pas à rejoindre ma formation dédiée à Next JS, où vous apprendrez à créer des applications performantes et réactives.