Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 34

Authentification Stateless avec JWT

Recommended resources

Bonjour ! Dans la leçon précédente, nous avons jeté les bases de la sécurité de notre application en explorant l'architecture de la SecurityFilterChain de Spring Security. Vous avez appris comment Spring intercepte les requêtes et comment nous pouvons commencer à définir nos propres règles de sécurité via un bean de configuration.

Nous avions conclu qu'il nous fallait un mécanisme d'authentification moderne, stateless, adapté à une API REST qui sera consommée par un frontend comme React. C'est précisément l'objectif de cette leçon : implémenter un système d'authentification stateless basé sur les JSON Web Tokens (JWT).

À la fin de cette leçon, vous aurez mis en place une brique essentielle de toute application web moderne : un système complet permettant à un utilisateur de s'inscrire, de se connecter pour obtenir un token, et d'utiliser ce token pour accéder aux ressources protégées de l'API.

1. Pourquoi des JWT ? Le concept de l'authentification Stateless

Avant de plonger dans le code, il est crucial de comprendre le problème que les JWT résolvent. Dans des frameworks plus anciens ou des applications monolithiques, l'authentification reposait souvent sur des sessions stockées côté serveur. Le serveur gardait en mémoire une "session" pour chaque utilisateur connecté.

Ce modèle présente des inconvénients majeurs pour les architectures modernes (microservices, API distribuées) :

  • Scalabilité difficile : Si vous avez plusieurs instances de votre serveur derrière un répartiteur de charge, comment vous assurez-vous que la session d'un utilisateur est partagée entre toutes les instances ?
  • Couplage fort : Le client (navigateur web, application mobile) et le serveur sont liés par cette session.

Les JWT proposent une solution élégante : l'authentification stateless (sans état). L'état de l'authentification n'est plus stocké sur le serveur, mais dans le token lui-même, qui est détenu par le client.

Pour une introduction claire et concise sur ce qu'est un JWT et comment il est structuré, je vous propose de visionner la vidéo suivante.

C'est quoi un JWT ?

Cette vidéo de la chaîne Kodaps explique de manière très pédagogique le concept des JWT, leur structure en trois parties (Header, Payload, Signature) et les avantages d'une architecture stateless.

Regardez le segment de 00:00 à 06:31. Concentrez-vous sur les points suivants : Le problème de l'authentification par session dans une architecture avec plusieurs serveurs. La définition d'un serveur "stateless". Les trois parties d'un JWT : l'en-tête (Header), le corps (Payload/Claims) et la signature. Le rôle de la signature pour garantir l'intégrité et l'authenticité du token.

Pour compléter, vous pouvez consulter la première partie de l'article de SFEIR Dev, qui résume ces caractéristiques.

Sécurisez vos API avec Spring Security : JWT - sfeir.dev

Cet article fournit une définition textuelle claire et les caractéristiques principales des JWT.

Lisez la section "Définition de JWT" pour renforcer votre compréhension de la structure et des avantages (Stateless, Autonome, Sécurisé).


2. Notre plan d'action : L'architecture de la solution

Maintenant que nous avons la théorie, voyons comment nous allons l'implémenter dans Spring Boot. Le diagramme ci-dessous illustre l'architecture que nous allons construire. C'est une représentation très fidèle de ce que font les professionnels.

Spring Boot JWT MySQL Spring Security Architecture
Ce diagramme montre comment une requête HTTP traverse les composants de Spring Security. Nous allons créer plusieurs de ces pièces : le `JwtAuthTokenFilter` (notre filtre personnalisé), le `JwtProvider` (notre service de gestion des tokens), et nous allons configurer `UserDetailsService` pour interagir avec notre base de données MySQL.

Voici les étapes que nous allons suivre :

  1. Ajouter les dépendances nécessaires pour Spring Security et la gestion des JWT.
  2. Créer une entité User et son Repository pour stocker les utilisateurs.
  3. Implémenter un UserDetailsService personnalisé pour charger les informations d'un utilisateur depuis la base de données.
  4. Créer un service JWTUtils pour la génération et la validation des tokens.
  5. Développer un JWTFilter, qui s'insérera dans la SecurityFilterChain. Son rôle sera d'inspecter chaque requête, de valider le token et d'authentifier l'utilisateur.
  6. Mettre à jour la SecurityConfig pour intégrer notre nouveau filtre et définir les règles d'accès.
  7. Créer un AuthController avec des endpoints pour l'inscription (/register) et la connexion (/login).

3. Mise en Œuvre Pratique

Pour la mise en œuvre, nous allons suivre une excellente vidéo qui vous guidera pas à pas dans la construction de ce système. Étant donné votre expérience avec Laravel, vous reconnaîtrez le concept de middleware dans notre JWTFilter.

Authentification par JWT avec Spring Security | Spring Boot | MySQL

La vidéo "Authentification par JWT avec Spring Security" de Coding With Armand est un tutoriel complet qui couvre toutes les étapes de notre plan d'action. Suivez-la attentivement pour construire le système d'authentification.

Regardez la vidéo du début jusqu'à 32:15. Je vous recommande de coder en même temps. Voici les segments clés : Dépendances et Configuration (00:00 - 03:10) : Ajout des dépendances Maven (spring-boot-starter-security, jjwt) et configuration de la clé secrète et de l'expiration du token dans application.properties. Modèle Utilisateur et Service (03:10 - 07:02) : Création de l'entité JPA User, de son UserRepository, et du CustomUserDetailsService qui implémente UserDetailsService. C'est ce service qui fait le pont entre Spring Security et votre base de données. Logique JWT (07:02 - 16:38) : Création de la classe JWTUtils. C'est le cœur du système. Portez une attention particulière aux méthodes generateToken, extractUsername et isTokenValid. Le Filtre JWT (16:38 - 23:00) : Implémentation du JWTFilter qui étend OncePerRequestFilter. Comprenez bien comment il extrait le token de l'en-tête Authorization: Bearer <token>, le valide, et si tout est correct, met à jour le SecurityContextHolder. C'est l'étape qui rend la session stateless. Configuration de Sécurité (23:00 - 27:20) : Mise à jour de SecurityConfig. Notez bien comment on désactive CSRF (.csrf(c -> c.disable())), on définit la politique de session sur STATELESS, on autorise les routes publiques (/api/auth/**), et surtout, comment on ajoute notre filtre avec .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class). Contrôleur d'Authentification (27:20 - 32:15) : Création du AuthController avec les endpoints /register et /login. La méthode login est cruciale : elle utilise AuthenticationManager pour vérifier les identifiants, et en cas de succès, génère et retourne un JWT.


4. Tester le flux d'authentification

Une fois que vous avez tout codé, il est temps de vérifier que tout fonctionne comme prévu. L'outil Postman (ou un équivalent) est parfait pour cela. Le flux de test est le suivant :

  1. Envoyer une requête POST à /api/auth/register avec un username et password dans le corps pour créer un nouvel utilisateur.
  2. Envoyer une requête POST à /api/auth/login avec les mêmes identifiants. Vous devriez recevoir en réponse un JSON contenant le token.
  3. Copier le token.
  4. Tenter d'accéder à une route protégée (par exemple, un GET sur /api/personnes si vous réutilisez le projet de CRUD précédent). Sans authentification, vous devriez recevoir une erreur 403 Forbidden ou 401 Unauthorized.
  5. Ré-exécuter la requête GET, mais cette fois, allez dans l'onglet "Authorization", choisissez le type "Bearer Token", et collez votre JWT dans le champ prévu. La requête devrait maintenant réussir et retourner les données.

La fin de la vidéo montre exactement ce processus.

Authentification par JWT avec Spring Security | Spring Boot | MySQL

Cette dernière partie de la vidéo de Coding With Armand vous montre comment utiliser Postman pour tester l'ensemble du système que vous venez de construire.

Regardez le segment de 32:15 à 34:49 pour voir une démonstration complète du test avec Postman.


Conclusion

Félicitations ! Vous avez implémenté un système d'authentification JWT complet et sécurisé, une compétence fondamentale pour tout développeur backend moderne.

Points clés à retenir :

  • Les JWT permettent une authentification stateless, où l'état de la connexion est contenu dans le token lui-même, ce qui est idéal pour les API REST et les architectures distribuées.
  • Le processus d'authentification avec JWT dans Spring Security repose sur plusieurs composants clés :
    • Un UserDetailsService pour charger les données de l'utilisateur.
    • Un service (JWTUtils ou JwtService) pour générer et valider les tokens.
    • Un filtre personnalisé (JWTFilter) qui intercepte les requêtes, extrait le token, et met à jour le contexte de sécurité (SecurityContextHolder).
    • Une configuration de sécurité (SecurityConfig) qui intègre ce filtre dans la chaîne de Spring Security (SecurityFilterChain).
  • Le flux est simple : le client s'authentifie une fois avec ses identifiants pour obtenir un JWT, puis il inclut ce JWT dans l'en-tête Authorization: Bearer ... de chaque requête subséquente vers les points de terminaison protégés.

Cependant, notre système a une petite faiblesse. Nos tokens ont une durée de vie fixe (15 minutes dans l'exemple). Si le token expire, l'utilisateur doit se reconnecter, ce qui peut être frustrant. Dans la prochaine leçon, nous aborderons ce problème en mettant en place un mécanisme de refresh tokens. Cela nous permettra de maintenir la sécurité des tokens à courte durée de vie tout en offrant une meilleure expérience utilisateur.