Authentication API
Systeme d'authentification complet : NextAuth.js v5, JWT, OAuth, sessions. Architecture unifiee pour la securisation de toutes les routes YaniPay.
Overview
YaniPay utilise un systeme d'authentification hybride combinant NextAuth.js v5 pour la gestion des sessions OAuth et des layouts proteges, et des JWT custompour l'authentification des routes API. Cette architecture garantit une securite maximale tout en offrant la flexibilite necessaire pour les clients web et mobile.
9 Endpoints
Registration, login, session, refresh, OAuth et legacy
CSRF + Rate Limit
Protection CSRF native. Auth : 5 req/15 min. Register/KYC : 10 req/min.
JWT + Sessions
Dual auth : cookies HttpOnly pour web, Bearer tokens pour API
Architecture
Le flux d'authentification YaniPay suit une architecture en couches qui separe la gestion des sessions (NextAuth) de l'authentification API (JWT custom).
Flux d'authentification
Login via formulaire ou OAuth provider
Validation credentials / OAuth, creation session
Token signe stocke en cookie securise, transmis automatiquement
Verification JWT dans chaque route API protegee
Dual Authentication System
getCurrentUser()est utilise pour toutes les routes API. Cette separation garantit cohérence et securite a travers l'application.API Endpoints
L'API d'authentification expose 9 endpoints couvrant le cycle complet : inscription, connexion, gestion de session, renouvellement de token et deconnexion.
| Methode | Endpoint | Description |
|---|---|---|
GETPOST | /api/auth/[...nextauth] | NextAuth.js handler (OAuth, sessions, callbacks) |
POST | /api/auth/register | Inscription utilisateur avec email et mot de passe |
POST | /api/auth/signin | Connexion email/password, retourne un JWT |
POST | /api/auth/signout | Deconnexion et invalidation de session |
GET | /api/auth/session | Recuperer la session active (NextAuth) |
POST | /api/auth/refresh | Renouveler le token JWT avant expiration |
GET | /api/auth/me | Profil de l'utilisateur authentifie |
POST | /api/auth/login | Legacy login (compatibilite mobile) |
POST | /api/auth/logout | Legacy logout (compatibilite mobile) |
Registration
Creez un nouveau compte utilisateur avec email, nom et mot de passe. Le mot de passe est hashe avec bcrypt (12 rounds) avant stockage en base de donnees.
Requete
const response = await fetch('/api/auth/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'Johan Lepinay',
email: 'johan@yanipay.com',
password: 'SecureP@ss123',
}),
});
const data = await response.json();
// Returns: { user: { id, name, email }, token: 'jwt...' }Reponse (201 Created)
1 { 2 "user": { 3 "id": "usr_a1b2c3d4e5f6", 4 "name": "Johan Lepinay", 5 "email": "johan@yanipay.com", 6 "role": "USER", 7 "createdAt": "2026-02-20T10:30:00Z" 8 }, 9 "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", 10 "expiresIn": 86400 11 }
Parametres requis
| Champ | Type | Validation |
|---|---|---|
| name | string | Min 2 caracteres, max 100 |
| string | Email valide, unique en base | |
| password | string | Min 8 caracteres, 1 majuscule, 1 chiffre, 1 special |
Sign In
Authentifiez un utilisateur avec email et mot de passe. Retourne un token JWT et set un cookie HttpOnly pour les requetes subsequentes.
Requete
const response = await fetch('/api/auth/signin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'johan@yanipay.com',
password: 'SecureP@ss123',
}),
});
const { user, token } = await response.json();Reponse (200 OK)
{
"user": {
"id": "usr_a1b2c3d4e5f6",
"name": "Johan Lepinay",
"email": "johan@yanipay.com",
"role": "USER",
"image": "https://avatars.githubusercontent.com/..."
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 86400,
"refreshToken": "rt_x1y2z3..."
}Session Management
La session active peut etre recuperee via NextAuth ou via le header Authorization pour les clients API.
Via NextAuth (composants React)
import { auth } from '@/auth';
export default async function ProtectedPage() {
const session = await auth();
if (!session) {
redirect('/auth/signin');
}
return (
<div>
<h1>Bienvenue, {session.user.name}</h1>
<p>Role: {session.user.role}</p>
</div>
);
}Via API (GET /api/auth/session)
const response = await fetch('/api/auth/session', {
credentials: 'include',
});
const session = await response.json();
if (session?.user) {
console.log(`Connecte en tant que ${session.user.email}`);
console.log(`Role: ${session.user.role}`);
} else {
console.log('Non authentifie');
window.location.href = '/auth/signin';
}Token Refresh
Renouvelez un token JWT avant son expiration sans demander a l'utilisateur de se reconnecter. Le refresh token a une duree de vie de 30 jours.
const response = await fetch('/api/auth/refresh', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
refreshToken: 'rt_x1y2z3...',
}),
});
const { token, expiresIn } = await response.json();
// New JWT token with fresh expiry{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 86400,
"refreshToken": "rt_new_a1b2c3..."
}Current User
Recuperez le profil complet de l'utilisateur authentifie, incluant role, preferences et metriques de compte.
const response = await fetch('/api/auth/me', {
headers: {
'Authorization': `Bearer ${token}`,
},
});
const { user } = await response.json();1 { 2 "user": { 3 "id": "usr_a1b2c3d4e5f6", 4 "name": "Johan Lepinay", 5 "email": "johan@yanipay.com", 6 "role": "ADMIN", 7 "image": "https://avatars.githubusercontent.com/...", 8 "emailVerified": "2026-01-15T08:00:00Z", 9 "createdAt": "2026-01-01T00:00:00Z", 10 "updatedAt": "2026-02-20T10:30:00Z", 11 "preferences": { 12 "language": "fr", 13 "currency": "EUR", 14 "notifications": true 15 }, 16 "accounts": [ 17 { 18 "provider": "github", 19 "linkedAt": "2026-01-01T00:00:00Z" 20 }, 21 { 22 "provider": "google", 23 "linkedAt": "2026-01-05T00:00:00Z" 24 } 25 ] 26 } 27 }
OAuth Providers
YaniPay supporte l'authentification via GitHub et Google en complement de l'authentification email/password. Les providers sont configures via les variables d'environnement.
GitHub
OAuth 2.0
GITHUB_IDGITHUB_SECRETOAuth 2.0 + OpenID Connect
GOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETimport { signIn } from 'next-auth/react';
// GitHub OAuth
await signIn('github', { callbackUrl: '/dashboard' });
// Google OAuth
await signIn('google', { callbackUrl: '/dashboard' });
// Email/Password via NextAuth
await signIn('credentials', {
email: 'johan@yanipay.com',
password: 'SecureP@ss123',
redirect: false,
});Callback URL
callbackUrldefinit la page de redirection apres une authentification reussie. Par defaut, l'utilisateur est redirige vers la page d'accueil. Pour les dashboards, utilisez /dashboard.JWT Token Structure
Les tokens JWT YaniPay utilisent l'algorithme HS256 et contiennent les claims suivants. Le secret de signature est configure via JWT_SECRETdans les variables d'environnement.
1 { 2 "sub": "usr_a1b2c3d4e5f6", 3 "email": "johan@yanipay.com", 4 "name": "Johan Lepinay", 5 "role": "ADMIN", 6 "iat": 1740048600, 7 "exp": 1740135000, 8 "iss": "yanipay.com", 9 "aud": "yanipay-api" 10 }
| Claim | Description | Exemple |
|---|---|---|
| sub | User ID unique | usr_a1b2c3d4e5f6 |
| Email de l'utilisateur | johan@yanipay.com | |
| role | Role RBAC Prisma : PARTICULIER, PROFESSIONNEL, EMPLOYE, ADMIN | PARTICULIER |
| iat | Issued at (timestamp UNIX) | 1740048600 |
| exp | Expiration (24h apres emission) | 1740135000 |
| iss | Issuer (domaine emetteur) | yanipay.com |
import { getCurrentUser } from '@/lib/auth';
export async function GET() {
const authResult = await getCurrentUser();
if (!authResult.success || !authResult.user) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
);
}
const { userId, email, role } = authResult.user;
// Proceed with authenticated operations...
}Securite
L'authentification YaniPay integre plusieurs couches de protection pour securiser les comptes utilisateurs et les donnees sensibles.
Rate Limiting
authRateLimit : 5 req/15 min (signin, login). strictRateLimit : 10 req/min (register, KYC, phone). Protection brute-force progressive.
CSRF Protection
Protection CSRF native via NextAuth.js et Server Actions. Double-submit cookie pattern pour les formulaires.
Secure Cookies
HttpOnly, Secure, SameSite=Lax. Les tokens ne sont jamais accessibles en JavaScript cote client.
Password Hashing
bcrypt avec 12 salt rounds. Les mots de passe ne sont jamais stockes en clair ou loggues.
Stockage des Tokens
localStorage. Utilisez les cookies HttpOnly configures automatiquement par NextAuth. Le localStorage est vulnerable aux attaques XSS et expose les tokens a du code JavaScript tiers. Les cookies HttpOnly sont inaccessibles via document.cookie et transmis automatiquement par le navigateur.RBAC — Roles autorisés par endpoint
Les routes protégées utilisent withAuth() de @/lib/auth/middleware ou vérifient le rôle manuellement après getCurrentUser(). Les rôles Prisma valides sont PARTICULIER, PROFESSIONNEL, EMPLOYE et ADMIN.
1 import { getCurrentUser } from '@/lib/auth'; 2 import { checkRateLimit, apiRateLimit } from '@/lib/rate-limit'; 3 import { unauthorizedResponse, forbiddenResponse, createApiResponse } from '@/lib/api/response'; 4 5 export async function GET(req: NextRequest) { 6 // Rate limiting 7 const rl = checkRateLimit(req, apiRateLimit); 8 if (!rl.success) { 9 return NextResponse.json({ error: 'Too many requests' }, { status: 429 }); 10 } 11 12 // Authentication — TOUJOURS getCurrentUser(), jamais auth() de next-auth 13 const auth = await getCurrentUser(req); 14 if (!auth.success || !auth.user) { 15 return unauthorizedResponse(); 16 } 17 18 // RBAC — roles Prisma exacts, ADMIN toujours inclus 19 const allowedRoles = ['PARTICULIER', 'ADMIN']; 20 if (!allowedRoles.includes(auth.user.role ?? '')) { 21 return forbiddenResponse(); 22 } 23 24 return createApiResponse({ data: {} }); 25 }
import { auth } from '@/auth';
import { NextResponse } from 'next/server';
export default auth((req) => {
const isLoggedIn = !!req.auth;
const isProtected = req.nextUrl.pathname.startsWith('/dashboard');
if (isProtected && !isLoggedIn) {
return NextResponse.redirect(new URL('/auth/signin', req.url));
}
return NextResponse.next();
});
export const config = {
matcher: ['/dashboard/:path*', '/api/billing/:path*'],
};Gestion des Erreurs
Les endpoints d'authentification retournent des erreurs structurees avec codes HTTP standard.
Bad Request
Parametres invalides (email mal forme, password trop court)
Unauthorized
Credentials invalides ou token expire
Forbidden
Compte bloque ou permissions insuffisantes (RBAC)
Not Found
Utilisateur introuvable pour cet email
Conflict
Email deja utilise lors de l'inscription
Too Many Requests
Rate limit depasse : 5 req/15 min (auth), 10 req/min (register/KYC). Header Retry-After inclus.
Internal Server Error
Erreur serveur inattendue
{
"error": "Invalid credentials",
"code": "AUTH_INVALID_CREDENTIALS",
"message": "Email or password is incorrect",
"retryAfter": null
}{
"error": "Too many requests",
"code": "AUTH_RATE_LIMIT",
"message": "Too many login attempts. Please try again in 60 seconds.",
"retryAfter": 60
}Ressources associees
Last updated: 2026-03-31