My App

Authentification

Better Auth, magic links, sessions, rôles

L'auth est gérée par Better Auth avec l'adapter Drizzle. Deux méthodes de connexion : magic link (onboarding) et email/password (quotidien).

Architecture

flowchart LR
    Client -->|credentials| BetterAuth[Better Auth]
    BetterAuth -->|session cookie| Client
    BetterAuth -->|vérifie| DB[(PostgreSQL)]
    Client -->|cookie httpOnly| API[tRPC API]
    API -->|getSession| BetterAuth

Méthodes de connexion

  1. Admin Wcare crée un établissement → un user est créé
  2. Better Auth génère un magic link (token one-time, validité 24h)
  3. Email envoyé via Resend
  4. Clic → session créée → redirect vers /dashboard
// Envoi du magic link via Better Auth
await auth.api.sendMagicLink({
  email: establishment.email,
  callbackURL: "/dashboard",
});

Email / Password

Disponible après la première connexion. L'établissement peut définir un mot de passe depuis ses paramètres.

// Sign in classique
await authClient.signIn.email({
  email: "hotel@example.com",
  password: "********",
});

Rôles et permissions

RôleAccèsCréation
super_adminToutSeed initial
establishment_adminSon établissementPar le super_admin
establishment_memberLecture seule + alertesPar l'establishment_admin

Middleware de rôle (tRPC)

const requireRole = (...roles: UserRole[]) =>
  protectedProcedure.use(({ ctx, next }) => {
    if (!roles.includes(ctx.session.user.role)) {
      throw new TRPCError({ code: "FORBIDDEN" });
    }
    return next({ ctx });
  });

const adminOnly = requireRole("super_admin");
const establishmentOnly = requireRole("establishment_admin", "super_admin");

Configuration Better Auth

betterAuth({
  database: drizzleAdapter(db, { provider: "pg", schema }),
  trustedOrigins: [env.CORS_ORIGIN],
  emailAndPassword: { enabled: true },
  magicLink: { enabled: true },
  secret: env.BETTER_AUTH_SECRET,
  baseURL: env.BETTER_AUTH_URL,
  advanced: {
    defaultCookieAttributes: {
      sameSite: "none",
      secure: true,
      httpOnly: true,
    },
  },
});

Sessions

  • Durée : 30 jours (configurable)
  • Stockage : Table session en PostgreSQL
  • Transport : Cookie httpOnly, secure, sameSite: none
  • Refresh : Automatique par Better Auth

On this page