Aller au contenu principal

Authentification

NextAuth v5 avec Google, Microsoft et Credentials. JWT, encryption, rate limiting.

Vue d'ensemble

HeartCo utilise NextAuth v5 (Auth.js) avec une stratégie JWT (pas de sessions en base). La session dure 24 heures.

Fichier principal : src/server/auth/config.ts

Providers

1. Google OAuth

GOOGLE_CLIENT_ID="xxxx.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET="GOCSPX-xxxx"

Configuration dans la Google Cloud Console :

  • Créer un projet → APIs & Services → Credentials → OAuth 2.0 Client ID
  • Authorized redirect URI : http://localhost:3000/api/auth/callback/google
  • En production : https://app.votre-domaine.fr/api/auth/callback/google

2. Microsoft Entra ID

MICROSOFT_CLIENT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
MICROSOFT_CLIENT_SECRET="xxxx"
MICROSOFT_TENANT_ID="common"

Configuration dans le portail Azure :

  • Azure AD → App registrations → New registration
  • Redirect URI : http://localhost:3000/api/auth/callback/microsoft-entra-id
  • Type : Web

Note : HeartCo bloque automatiquement les comptes Microsoft personnels (Consumer Tenant). Seuls les comptes organisationnels sont acceptés.

3. Credentials (Email + Mot de passe)

Authentification classique par email/mot de passe avec :

  • Rate limiting : 10 tentatives par IP toutes les 15 minutes (Upstash Redis)
  • Protection timing attack : bcrypt.compare() exécuté même si l'utilisateur n'existe pas
  • Normalisation email : lowercase + trim automatique
  • Vérification email : obligatoire avant connexion

Flow d'inscription

Register (/register)
    │
    ▼
Création du compte + Organisation
    │
    ▼
Email de vérification (Resend)
    │
    ▼
Verify Email (/verify-email)
    │
    ▼
Onboarding (/onboarding)
    │  - Nom de l'organisation
    │  - Secteur d'activité
    │  - Configuration initiale
    ▼
Dashboard (/dashboard)

Pour les providers OAuth (Google, Microsoft), l'email est automatiquement vérifié et l'utilisateur passe directement à l'onboarding.

Rôles

HeartCo définit 7 rôles avec une hiérarchie stricte :

RôleNiveauDescription
ADMIN0Accès total à l'organisation
DIRECTION1Direction — lecture étendue + validation
MANAGER2Gestion opérationnelle (factures, devis, clients)
HR3Ressources humaines (congés, fiches de paie)
ACCOUNTANT3Comptabilité (FEC, rapprochements)
COLLABORATOR4Accès limité (ses propres données)
CLIENT99Portail client uniquement (aucune permission interne)

Les rôles HR et ACCOUNTANT sont au même niveau hiérarchique (3) mais avec des permissions différentes. Voir Permissions.

Routes API d'authentification

RouteMéthodeDescription
/api/auth/[...nextauth]GET/POSTHandlers NextAuth (login, callback, session)
/api/auth/accept-invitePOSTAccepter une invitation d'équipe
/api/auth/forgot-passwordPOSTDemande de réinitialisation de mot de passe
/api/auth/reset-passwordPOSTRéinitialiser le mot de passe (avec token)
/api/auth/verify-emailGETVérifier l'adresse email (lien dans l'email)
/api/auth/resend-verificationPOSTRenvoyer l'email de vérification
/api/auth/mobile/loginPOSTConnexion depuis l'app mobile (JWT)
/api/auth/mobile/refreshPOSTRafraîchir le token mobile
/api/auth/mobile/delete-accountDELETESupprimer le compte (app mobile)

Sécurité

Token Encryption

Les tokens OAuth (Google, Microsoft) sont chiffrés au repos avec AES-256-GCM avant d'être stockés en base :

TOKEN_ENCRYPTION_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# 64 caractères hex (32 bytes) — Générer : openssl rand -hex 32

Rate Limiting

Les tentatives de connexion par Credentials sont limitées à 10 par IP sur 15 minutes :

  • Backend : Upstash Redis (sliding window)
  • Fallback : compteur en mémoire si Redis indisponible

Auto-refresh des tokens OAuth

Les tokens Google et Microsoft sont automatiquement rafraîchis s'ils expirent dans les 5 prochaines minutes. Aucune intervention de l'utilisateur n'est nécessaire.

Protection contre les redirections ouvertes

Le callback NextAuth vérifie que l'URL de redirection est sur le même domaine (same-origin). Les redirections externes sont bloquées.

Session

La session JWT contient :

interface Session {
  user: {
    id: string;                    // ID utilisateur
    name: string;
    email: string;
    image: string | null;
    role: string;                  // Rôle dans l'organisation
    organizationId: string | null; // ID de l'organisation
    emailVerified: boolean;
    emailAccountId?: string | null;
  };
}

Accès côté serveur :

// Dans un router tRPC
const userId = ctx.session.user.id;
const orgId = ctx.session.user.organizationId;
const role = ctx.session.user.role;

Accès côté client :

import { useSession } from "next-auth/react";
 
const { data: session } = useSession();
console.log(session?.user.role);

Ajouter un nouveau provider OAuth

  1. Installer le provider (si nécessaire) — NextAuth v5 inclut les providers courants.

  2. Ajouter les variables d'environnement dans .env et src/env.js :

// src/env.js — section server
NEW_PROVIDER_CLIENT_ID: z.string().optional(),
NEW_PROVIDER_CLIENT_SECRET: z.string().optional(),
  1. Configurer le provider dans src/server/auth/config.ts :
import NewProvider from "next-auth/providers/new-provider";
 
providers: [
  // ... providers existants
  NewProvider({
    clientId: env.NEW_PROVIDER_CLIENT_ID,
    clientSecret: env.NEW_PROVIDER_CLIENT_SECRET,
  }),
],
  1. Ajouter le bouton dans la page de login (src/app/login/page.tsx).

  2. Tester : Vérifiez le flow complet (login → callback → session → dashboard).