Next.jsTypeScriptSécurité

Implémenter une Basic Auth dans Next.js App Router

Publié le

Dimitri Dumont
Dimitri Dumont

Développeur React & Next.js freelance

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 fonctionnement 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
BASIC_AUTH_DISABLED=false
BASIC_AUTH_USER=username
BASIC_AUTH_PASSWORD=password

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
export const GET = () => {
  return new Response("Authentication Required!", {
    status: 401,
    headers: {
      "WWW-Authenticate": "Basic realm='private_pages'",
    },
  })
}

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
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
 
export function middleware(req: NextRequest) {
  if (
    process.env.BASIC_AUTH_DISABLED === "true" ||
    process.env.NODE_ENV === "development"
  )
    return NextResponse.next()
 
  const basicAuth = req.headers.get("authorization")
 
  if (basicAuth) {
    const authValue = basicAuth.split(" ")[1]
 
    const [username, password] = atob(authValue).split(":")
 
    if (
      username === process.env.BASIC_AUTH_USER &&
      password === process.env.BASIC_AUTH_PASSWORD
    )
      return NextResponse.next()
  }
 
  const url = req.nextUrl
  url.pathname = "/api/auth"
 
  return NextResponse.rewrite(url)
}
 
export const config = {
  matcher: ["/"],
}

Pour commencer, nous vérifions si l'authentification est désactivé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
if (
  process.env.BASIC_AUTH_DISABLED === "true" ||
  process.env.NODE_ENV === "development"
)
  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
const basicAuth = req.headers.get("authorization")
 
if (basicAuth) {
  const authValue = basicAuth.split(" ")[1]
 
  const [username, password] = atob(authValue).split(":")
 
  if (
    username === process.env.BASIC_AUTH_USER &&
    password === process.env.BASIC_AUTH_PASSWORD
  )
    return NextResponse.next()
}

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

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

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

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

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.

Cet article vous a été utile ?

Je peux vous accompagner sur votre projet React & Next.js.

Discutons de votre projet →

Articles similaires