Comment implémenter une Basic Auth dans un projet Next.js v14+ ?

Publié le 8 mai 2024
Dimitri Dumont avatar
Dimitri Dumont
Développeur front-end

Que ce soit pour implémenter une simple authentification ou pour protéger l'accès à votre application le temps de sa mise en production, l'authentification "Basic Auth" ou aussi appelée "HTTP authentication" est une solution simple et efficace. Dans ce tutoriel, nous allons voir comment implémenter une Basic Auth dans un projet Next.js v14+ avec l'app router.

Qu'est-ce que Basic Auth ?

Pour comprendre comment l'implémenter dans un projet Next.js, il est utile de comprendre le fonction de cette authentification HTTP.

Son fonctionnement est relativement simple :

  1. Un visiteur tente d'accéder à une page protégée.
  2. Le serveur envoie une réponse avec un statut 401 et fourni l'information pour permettre à l'utilisateur de s'authentifier grâce à un en-tête de réponse WWW-Authenticate.
  3. Le visiteur s'authentifie grâce à une fenêtre qui contient le formulaire d'authentification.
  4. Le navigateur encode en base64 les identifiants du visiteur et les transmet au serveur en incluant un en-tête Authorization.
  5. Le serveur vérifie les identifiants et renvoie une réponse avec le statut 200 ou 403 en fonction de la vérification des identifiants.
  6. Le navigateur garde en cache ces identifiants jusqu'à ce que l'onglet soit fermé.

Les étapes pour implémenter Basic Auth dans Next.js

Pour implémenter une "Basic Auth" dans un projet Next.js avec l'app router, il faut suivre ces étapes :

  1. Déclarer des variables d'environnement pour stocker des identifiants.
  2. Créer une route handler pour proposer une interface d'authentification à l'utilisateur.
  3. Créer un middleware pour vérifier si l'utilisateur est connecté ou non et le rediriger.

1. Déclaration des variables d'environnement

Pour cet article, nous allons définir les identifiants dans les variables d'environnement. Vous pouvez également ajouter une autre variable d'environnement qui servira à activer ou non l'authentification en fonction de certains cas comme des tests end-to-end ou des tests Lighthouse.

.env.local
1BASIC_AUTH_DISABLED=false
2BASIC_AUTH_USER=username
3BASIC_AUTH_PASSWORD=password
hexa web logo
Hexa web
Des conseils pour un projet web ?
Nous contacter

2. Création de la route handler

Cette route handler va permettre à Next.js de renvoyer une erreur 401 pour demander à l'utilisateur de s'authentifier via une interface directement intégrée dans le navigateur.

src/app/api/auth/route.ts
1export const GET = () => {
2 return new Response("Authentication Required!", {
3 status: 401,
4 headers: {
5 "WWW-Authenticate": "Basic realm='private_pages'",
6 },
7 })
8}

3. Configuration du middleware

Une fois les variables d'environnement initialisées et la route handler crée, nous pouvons créer un middleware pour protéger l'accès à notre application Next.js.

src/middleware.ts
1import { NextResponse } from "next/server"
2import type { NextRequest } from "next/server"
3
4export function middleware(req: NextRequest) {
5 if (
6 process.env.BASIC_AUTH_DISABLED === "true" ||
7 process.env.NODE_ENV === "development"
8 )
9 return NextResponse.next()
10
11 const basicAuth = req.headers.get("authorization")
12
13 if (basicAuth) {
14 const authValue = basicAuth.split(" ")[1]
15
16 const [username, password] = atob(authValue).split(":")
17
18 if (
19 username === process.env.BASIC_AUTH_USER &&
20 password === process.env.BASIC_AUTH_PASSWORD
21 )
22 return NextResponse.next()
23 }
24
25 const url = req.nextUrl
26 url.pathname = "/api/auth"
27
28 return NextResponse.rewrite(url)
29}
30
31export const config = {
32 matcher: ["/"],
33}
34

Pour commencer, nous vérifions si l'authentification est déactivée grâce à une variable d'environnement ou si nous sommes dans un environnement de développement. Si cette condition est vraie, alors nous n'utilisons pas l'authentification.

src/middleware.ts
1if (
2 process.env.BASIC_AUTH_DISABLED === "true" ||
3 process.env.NODE_ENV === "development"
4)
5 return NextResponse.next()

Si l'authentification doit être utilisée, alors nous commençons par récupérer la valeur du header authorization depuis la requête entrante. Si ce header contient une valeur, alors nous tentons de récupérer les identifiants username et password.

Si ces valeurs correspondent aux identifiants présents dans les variables d'environnement, alors l'utilisateur est authentifié et il peut accéder à l'URL qu'il souhaite.

src/middleware.ts
1const basicAuth = req.headers.get("authorization")
2
3if (basicAuth) {
4 const authValue = basicAuth.split(" ")[1]
5
6 const [username, password] = atob(authValue).split(":")
7
8 if (
9 username === process.env.BASIC_AUTH_USER &&
10 password === process.env.BASIC_AUTH_PASSWORD
11 )
12 return NextResponse.next()
13}

Sinon, il est redirigé sur une route handler pour lui demander de s'authentifier.

src/middleware.ts
1const url = req.nextUrl
2url.pathname = "/api/auth"
3
4return NextResponse.rewrite(url)

Enfin, grâce à l'objet config vous pouvez choisir quelles urls demandent une authentification.

src/middleware.ts
1export const config = {
2 matcher: ["/"],
3}

Conclusion

Implémenter une "Basic Authentification" ou "HTTP authentication" dans une application Next.js qui utilise l'app router n'est pas très compliqué et peut vous permettre de sécuriser l'accès à votre application pour certains cas.

Cette authentification peut être utilisée pour empêcher l'accès à votre site internet ou à votre application Next.js le temps de développer votre projet ou pour des fonctionnalités en cours de développement.

Échangeons sur votre projet web

Présentez-nous votre projet web, nous vous recontacterons dans les prochaines 24h.