LogoKalli
Server

Authentication & Authorization

Authentification & Autorisation

  • Lib: Better Auth avec adapter Drizzle et plugin admin.
  • Montée Hono: routes servies sous /api/auth/**.
  • RBAC: rôles user et admin via plugin admin.

Fichiers & intégration

  • Server:

    • apps/server/src/lib/auth.ts — configuration Better Auth
      • Sessions (maxAge/updateAge), drizzle adapter, trustedOrigins
      • Email reset via Resend (sendEmail())
      • OAuth Microsoft (MICROSOFT_CLIENT_ID/SECRET/TENANT_ID)
    • apps/server/src/index.ts — montage des routes auth
      • app.on(["POST","GET"], "/api/auth/**", (c) => auth.handler(c.req.raw))
    • apps/server/src/lib/context.ts — récupération session côté RPC
  • Web:

    • apps/web/src/lib/auth-client.tscreateAuthClient({ baseURL })
    • Important: baseURL doit pointer vers le chemin où le handler est monté.
      • Si le serveur monte sous /api/auth/**, alors utiliser baseURL = ${VITE_SERVER_URL}/api/auth.

Variables d'environnement (server)

  • CORS_ORIGIN — origine autorisée (ex: http://localhost:3001)
  • BETTER_AUTH_SECRET — secret de chiffrement des sessions
  • BETTER_AUTH_URL — URL publique d'auth (ex: http://localhost:3000)
  • RESEND_API_KEY, EMAIL_FROM — envoi d'emails (reset password)
  • MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, MICROSOFT_TENANT_ID — OAuth

Voir l'exemple : apps/server/.env-example.

Endpoints & baseURL

  • Montage serveur: app.on(["POST","GET"], "/api/auth/**", (c) => auth.handler(c.req.raw)) dans apps/server/src/index.ts.
  • Cela implique que la racine d'auth est /api/auth (ex: http://localhost:3000/api/auth).
  • Côté client Better Auth, définissez baseURL vers cette racine:
// apps/web/src/lib/auth-client.ts
import { createAuthClient } from "better-auth/react";
import { getServerUrl } from "@/utils/runtime-env";

export const authClient = createAuthClient({
  baseURL: `${getServerUrl()}/api/auth`, // IMPORTANT: refléter le montage serveur
});

Sans ce suffixe /api/auth, le client appellera /sign-in/email au lieu de /api/auth/sign-in/email (404 probable). Adaptez selon votre proxy/ingress si vous réécrivez les chemins.

Cookies, CORS et sessions

  • CORS (hono/cors) est configuré avec credentials: true et une origine autorisée dynamique + CORS_ORIGIN.
  • Le client ORPC utilise credentials: 'include' pour inclure les cookies.
  • Assurez-vous que:
    • le front et le back partagent un domaine/port compatible avec SameSite (en dev: ports différents OK si credentials: true + CORS).
    • trustedOrigins dans auth.ts inclut l'origine front (process.env.CORS_ORIGIN).
  • Sessions: maxAge: 86400, updateAge: 3600 (config par défaut dans auth.ts).

Flux typiques

  1. Email + mot de passe
    • POST /api/auth/sign-in/email avec email/password → cookie de session.
    • Reset password: sendResetPassword via Resend; url générée par Better Auth.
  2. Microsoft OAuth
    • Démarre le flow OAuth Microsoft → redirige vers callback Better Auth.
  3. Vérification côté client
    • Les routes protégées appellent getMe (ORPC) pour vérifier la session.

Débogage & erreurs courantes

  • 404 sur /sign-in/email: baseURL côté client ne pointe pas vers /api/auth.
  • 401 UNAUTHORIZED: pas de cookie de session (ou expiré); vérifier credentials: 'include'.
  • 403 FORBIDDEN: rôle insuffisant (voir plugin admin et RBAC ORPC).
  • CORS: vérifier CORS_ORIGIN et l'origine exacte (schéma + host + port).

Accès protégé (ORPC)

  • Middlewares dans apps/server/src/lib/orpc.ts :
    • protectedProcedure — nécessite session valide
    • adminProcedure — nécessite role === 'admin'
    • Erreurs standardisées: UNAUTHORIZED, FORBIDDEN