Pratique

Authentification & Admin

Configurer des rôles admin en lecture seule et lecture/écriture, protéger les APIs admin et comprendre le pipeline d’authentification.

Authentification & Admin

Ce template utilise Better Auth + Drizzle. Le RBAC est stocké en base de données, sans élévation via des variables d’environnement.

Notions de base : authentification vs autorisation

  • Authentification : prouve qui vous êtes (inscription/connexion). Le résultat est une session.
  • Autorisation : décide ce que vous pouvez faire après connexion. Ici, c’est le champ role de la table users qui pilote l’accès.

Rôles :

  • user — par défaut pour tout le monde.
  • admin_ro — lecture seule (visualisation des données admin, pas d’écriture).
  • admin_rw — lecture + écriture (inclut l’octroi de crédits et autres actions admin).

Une analogie simple

À l’aéroport, montrer votre pièce d’identité au contrôle est l’authentification (prouver votre identité). Présenter votre carte d’embarquement à la porte est l’autorisation (vérifier que vous êtes autorisé à monter dans cet avion).

Comparaison rapide

SujetAuthentificationAutorisation
ObjectifVérifier l’identité (qui)Vérifier les permissions (quoi)
MomentAvant l’autorisationAprès une authentification réussie
Entrées typiquesIdentifiants (mot de passe, lien email, social)Politiques/rôles (user, admin_ro, admin_rw)
SortieSession/identitéActions autorisées et routes protégées
Standards (généraux)OIDC, ID TokensOAuth 2.0, scopes

Dans ce template : sessions via cookies HttpOnly côté serveur (pas de jeton front), et un simple rôle en base pour la logique d’autorisation.

Qu’est‑ce que Better Auth ?

Librairie d’auth légère et orientée TypeScript pour Next.js.

  • Stockage : Drizzle ORM + Postgres (voir src/lib/auth.ts).
  • Modèle de données : users, sessions, accounts, verifications (voir src/db/schema.ts).
  • Sessions : cookie HttpOnly et ligne dans sessions ; côté serveur, lecture via auth.api.getSession({ headers }).
  • Champs additionnels : uuid et role sont exposés à la session via additionalFields pour faciliter les contrôles côté serveur.

Secrets et URLs (niveau débutant)

  • BETTER_AUTH_SECRET : secret long et aléatoire côté serveur pour signer/vérifier les cookies/jetons. À générer une fois et à garder privé.
    • Génération : openssl rand -base64 32
    • Rotation : changer la valeur déconnecte tous les utilisateurs (sessions invalidées).
  • BETTER_AUTH_URL : base URL côté serveur pour la lib d’auth (souvent l’URL du site).
  • NEXT_PUBLIC_AUTH_BASE_URL : base côté client (identique au site dans la plupart des cas).
  • Cookies en HttpOnly et secure en production (voir advanced.defaultCookieAttributes dans src/lib/auth.ts).

Si une connexion ne tient pas ou disparaît au redémarrage, vérifiez ces variables et redémarrez le serveur de dev.

Rôles

  • user : rôle par défaut.
  • admin_ro : lecture seule ; lister les utilisateurs/commandes et voir les crédits d’un utilisateur.
  • admin_rw : lecture + opérations ; peut aussi accorder des crédits (trans_type = system_add).

La migration 0001_add_user_role.sql ajoute users.role avec la valeur par défaut user.

Autorisation

  • src/lib/authz.ts lit le rôle depuis la session/BD :
    • requireAdminRead() → autorise admin_ro/admin_rw.
    • requireAdminWrite() → autorise admin_rw.

APIs Admin

  • GET /api/admin/users → liste des utilisateurs (pagination page, limit).
  • GET /api/admin/orders → commandes payées (pagination).
  • GET /api/admin/users/:uuid/credits → résumé des crédits.
  • POST /api/admin/credits/grant → accorde des crédits (system_add).

Mise en place

  1. Migrer la base :
pnpm drizzle-kit migrate --config src/db/config.ts
  1. Vérifier les endpoints (avec un compte admin).

Modifier les rôles

La base de données est la source d’autorité :

  • SQL :
    update users set role = 'admin_rw' where uuid = '<uuid>';
  • Helper :
    • updateUserRole(uuid, 'admin_ro' | 'admin_rw' | 'user') dans src/models/user.ts.

Remarques

  • Protéger les comptes admin (MFA/SSO) et réduire la durée des sessions.
  • Protéger les pages admin côté serveur et rediriger si non autorisé.
  • Pas de rôles via .env ; utilisez la base pour assigner/révoquer.

Connexion sociale (Google)

  • Le provider Google est configuré dans src/lib/auth.ts sous socialProviders.google et lit GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET depuis .env.
  • Vérifiez les variables : GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, ainsi que BETTER_AUTH_URL et NEXT_PUBLIC_AUTH_BASE_URL (ex. http://localhost:3000 en dev).
  • Dans Google Cloud Console → Identifiants, ajoutez l’URI de redirection autorisée :
    • http://localhost:3000/api/auth/callback/google (dev)
    • https://votre-domaine.com/api/auth/callback/google (prod)
  • L’écran /[locale]/login affiche un bouton “Continuer avec Google” qui lance le flux OAuth.