JWT Authentication Pattern (SPA + REST API)
Authentication Flow
sequenceDiagram
participant User
participant Frontend
participant Backend
participant DB
User->>Frontend: Login
Frontend->>Backend: POST /auth/login
Backend->>DB: Verify credentials
DB-->>Backend: Credentials valid
Backend-->>Frontend: Access + Refresh tokens
Frontend->>Backend: API request (with Access token)
Backend-->>Frontend: Response
Contexte
Les applications modernes utilisent souvent une architecture séparée :
- frontend SPA (React, Vue, Angular)
- backend API REST
Dans ce modèle, le backend doit authentifier les utilisateurs sans utiliser de sessions serveur.
Les mécanismes traditionnels basés sur les sessions HTTP deviennent difficiles à gérer dans :
- les architectures distribuées
- les systèmes conteneurisés
- les environnements cloud
Une solution largement adoptée consiste à utiliser JWT (JSON Web Tokens).
Principe
Un JWT est un token signé contenant les informations nécessaires pour identifier un utilisateur.
Exemple de contenu :
{
"sub": "user-id",
"role": "ADMIN",
"exp": 1712345678
}
Le serveur signe ce token.
Le client l'utilise ensuite pour authentifier les requêtes.
Architecture typique
Architecture simplifiée :
flowchart TD
U[User / Browser] --> F[Frontend - React App]
F -->|HTTP Requests| B[Backend API]
B -->|Queries| D[(Database)]
Le frontend communique uniquement
avec l'API.
L'API valide les tokens JWT.
Access Token et Refresh Token
Une bonne pratique consiste à utiliser deux types de tokens.
Access Token
Le access token :
- contient l'identité de l'utilisateur
- contient les rôles
- a une durée de vie courte
Exemple :
5 à 15 minutes
Il est utilisé pour :
- authentifier les requêtes API
Refresh Token
Le refresh token permet de renouveler un access token expiré.
Il possède une durée de vie plus longue.
Exemple :
7 à 30 jours
Le refresh token évite de redemander les credentials.
Flux d'authentification
Login
POST /auth/login
Le serveur :
- valide les credentials
- génère access token + refresh token
- renvoie les tokens
Utilisation de l'API
Le client envoie l'access token à chaque requête.
Exemple :
Authorization: Bearer <access_token>
Le serveur valide :
- la signature
- l'expiration
- les rôles
Refresh
Lorsque l'access token expire :
POST /auth/refresh
Le serveur vérifie le refresh token et génère un nouveau access token.
Stockage des tokens
Plusieurs stratégies existent.
Local Storage
Le token est stocké dans le local storage.
Avantage :
- simplicité
Inconvénient :
- vulnérable aux attaques XSS
Cookies HttpOnly
Une approche plus sécurisée consiste à stocker les tokens dans des cookies HttpOnly.
Avantages
- inaccessible au JavaScript
- réduit les risques XSS
Les cookies peuvent être configurés avec :
HttpOnly
Secure
SameSite
Sécurité
Plusieurs bonnes pratiques sont recommandées.
Durée de vie courte
Les access tokens doivent expirer rapidement.
Signature forte
Les tokens doivent être signés avec une clé sécurisée.
Rotation des refresh tokens
Dans certains systèmes, le refresh token est remplacé à chaque utilisation.
Contrôle d'accès
Les rôles présents dans le JWT permettent d'appliquer des règles d'autorisation.
Exemple :
ROLE_ADMIN
ROLE_USER
Avantages
JWT permet :
- une API stateless
- une bonne scalabilité
- une compatibilité avec les SPA
- une architecture simple
Limites
JWT introduit certains défis :
- gestion de la révocation
- gestion des refresh tokens
- sécurisation du stockage
Une mauvaise implémentation peut introduire des failles.
Conclusion
JWT est aujourd'hui une solution courante pour sécuriser les API dans les architectures modernes.
Associé à :
- refresh tokens
- cookies HttpOnly
- contrôle RBAC
il permet de construire une authentification robuste pour les applications web modernes.