Vous êtes sur la page 1sur 8

JSON Web Token (JWT) et

Authentification
Nous allons explorer l'API REST et l'authentification et l'autorisation JWT à l'aide de Spring
Boot 3 et Spring Security 6. Tout d'abord, examinons l'API REST et un exemple
d'authentification JWT.

1 L'API REST
REST, qui signifie REpresentational State Transfer, est un style architectural pour la
conception d'applications en réseau. REST est devenu la méthode prédominante de
conception d'une API (interface de programmation d'application) pour les applications basées
sur le web.
Les API REST fournissent une manière structurée et normalisée pour que différentes
applications logicielles puissent communiquer sur Internet. Elles sont devenues l'épine dorsale
des applications web et mobiles modernes, permettant une intégration et une interaction
fluides entre divers services et systèmes.
Les API REST permettent à différentes applications logicielles de communiquer et d'interagir
les unes avec les autres sur Internet en utilisant des méthodes HTTP standard.
Les concepts clés de l'API REST sont les suivants :
 Ressources : En REST, tout est considéré comme une ressource. Une ressource peut
être une entité de données, un objet, ou tout autre type d'information pouvant être
identifié par une URL unique (Uniform Resource Locator).
 Méthodes HTTP : Les API REST utilisent les méthodes HTTP standard pour effectuer
des opérations sur les ressources, telles que :
 GET récupère des données depuis le serveur.
 POST envoie des données au serveur pour créer une nouvelle ressource.
 PUT met à jour une ressource existante sur le serveur.
 DELETE supprime une ressource du serveur.
 PATCH met à jour partiellement une ressource.
 Interface uniforme : Les API REST possèdent une interface uniforme et cohérente.
Chaque ressource est identifiée par une URL, et différentes méthodes HTTP sont
utilisées pour interagir avec ces ressources.
 Stateless (sans état) : Chaque requête d'API d'un client vers un serveur doit contenir
toutes les informations nécessaires pour comprendre et répondre à la demande. Le
serveur ne stocke aucun état client entre les requêtes.
 Architecture client-serveur : REST sépare le client (l'application faisant la demande)
du serveur (l'application répondant à la demande), ce qui leur permet d'évoluer
indépendamment.
 Format de réponse : Les API REST retournent généralement des données dans des
formats courants tels que JSON (JavaScript Object Notation) ou XML (eXtensible
Markup Language).
Voici des exemples simples d'une API REST gérant une liste de voitures.

 GET /cars : Récupérer la liste de toutes les voitures.


 GET /cars/{id} : Récupérer les détails d'une voiture spécifique.
 POST /cars : Créer un nouveau dossier de voiture en envoyant des données sur la
voiture.
 PUT /cars/{id} : Mettre à jour les détails d'une voiture spécifique.
 DELETE /cars/{id} : Supprimer une voiture spécifique.

Ce qui suit décrit les avantages les plus importants des API REST.

 Scalabilité : Les architectures RESTful sont évolutives en raison de leur nature sans
état.
 Flexibilité : Les clients et les serveurs peuvent évoluer indépendamment sans s'affecter
mutuellement si le contrat de l'API reste cohérent.
 Adoption étendue : REST est largement adopté et compris, ce qui facilite le travail des
développeurs.
 Mise en cache : Les API REST peuvent utiliser les mécanismes de mise en cache
HTTP pour améliorer les performances.
 Indépendance linguistique et de plateforme : Puisque les API REST utilisent des
méthodes et des formats HTTP standard, elles peuvent être accédées depuis divers
langages de programmation et plates-formes.
Bien que les API REST présentent de nombreux avantages, il existe également quelques
inconvénients et limitations à prendre en compte.

 Manque de normalisation : Malgré son adoption généralisée en tant que style


architectural, REST ne fournit pas de directives strictes sur la conception des API.
Cela peut entraîner des incohérences dans la conception des API et rendre difficile la
garantie de l'uniformité entre différentes API.
 Sur-sollicitation et sous-sollicitation : Les API REST renvoient souvent des structures
de données fixes, ce qui peut entraîner une sur-sollicitation (recevoir plus de données
que nécessaire) ou une sous-sollicitation (recevoir moins de données que nécessaire).
Cela peut entraîner un gaspillage de bande passante ou des demandes supplémentaires.
 Support limité pour la communication en temps réel : Les API REST sont
généralement basées sur la requête-réponse et peuvent ne pas être bien adaptées à la
communication en temps réel. La mise en œuvre de fonctionnalités telles que la
messagerie instantanée ou les mises à jour en direct peut être complexe et nécessiter
des technologies supplémentaires.
 Absence de gestion intégrée de l'état : Les API REST sont sans état, ce qui signifie
que le serveur ne stocke pas l'état du client. Bien que cela simplifie la conception du
serveur, la gestion des informations liées à la session peut poser des défis.
 Absence de sémantique riche : Les API REST reposent principalement sur les
méthodes et codes d'état HTTP, qui ne transmettent pas toujours une sémantique riche
sur les opérations sous-jacentes. Cela peut entraîner une ambiguïté dans la
compréhension du but de certaines API.
 Surcoût de performance : Les API REST peuvent impliquer des étapes
supplémentaires de traitement et de sérialisation des données en raison de la
dépendance à des formats tels que JSON ou XML. Cela peut introduire un surcoût de
performance, en particulier dans des scénarios à haute fréquence.
 Multiples requêtes pour des opérations complexes : Les opérations complexes
nécessitent souvent plusieurs requêtes au serveur, entraînant une surcharge réseau
supplémentaire et une latence. Cela peut être préoccupant pour les applications
mobiles ou dans des situations de bande passante limitée.
 Manque de flexibilité dans la version : Modifier une API REST tout en maintenant la
compatibilité ascendante peut être difficile. Différentes versions de l'API peuvent
nécessiter une gestion, ce qui peut compliquer le processus de développement et de
déploiement.
 Considérations de sécurité : Bien que les API REST puissent être sécurisées à l'aide de
mécanismes tels que HTTPS et l'authentification, la conception d'une API REST
sécurisée nécessite une réflexion attentive sur l'autorisation, la gestion des jetons et la
protection contre les vulnérabilités de sécurité courantes.
 Découvrabilité limitée : Découvrir les points d'extrémité disponibles et leurs
fonctionnalités dans une API REST peut nécessiter une documentation externe, car il
n'existe pas de mécanisme intégré pour exposer la structure de l'API aux clients.

2 INTRODUCTION AUX JSON WEB TOKENS


JWT est une norme ouverte (RFC 7519) qui définit une manière compacte et autonome de
transmettre des informations de manière sécurisée entre des parties sous la forme d'un objet
JSON. Les JWT sont couramment utilisés pour l'authentification et l'autorisation dans les
applications web et les API.
Un JWT se compose de trois parties :
En-tête (Header) : L'en-tête se compose généralement de deux parties : le type de jeton
(JWT) et l'algorithme de signature utilisé, tel que HMAC SHA256 ou RSA.

{
"alg": "HS256",
"typ": "JWT"
}

Charge utile (Payload) : La deuxième partie du jeton est la charge utile, qui contient les
assertions. Les assertions (Claims) sont des déclarations sur une entité (généralement
l'utilisateur) et des métadonnées supplémentaires, et peuvent être catégorisées en trois types.

 Les assertions enregistrées sont des assertions prédéfinies avec des significations
spécifiques, telles que iss (émetteur), exp (heure d'expiration), sub (sujet), et plus
encore.
 Les assertions publiques sont des assertions personnalisées que vous définissez pour
transmettre des informations supplémentaires.
 Les assertions privées sont des assertions personnalisées destinées à être partagées
entre des parties qui conviennent de leur utilisation et ne sont pas définies dans une
spécification publique.

{
"sub": "1234567890",
"name": "Massimo Nardone",
"iat": 6723561290
}

Signature : Pour créer une signature, vous devez signer l'en-tête encodé, la charge utile
encodée, un secret et l'algorithme spécifié dans l'en-tête. La signature est utilisée pour vérifier
que l'expéditeur du JWT est bien celui qu'il prétend être et pour s'assurer que le message n'a
pas été modifié en cours de route.
Ce qui suit explique comment les JWT fonctionnent.

 Authentification : Lorsqu'un utilisateur se connecte, le serveur crée un JWT


contenant les informations de l'utilisateur et le signe avec une clé secrète. Ce JWT est
ensuite envoyé au client.
 Autorisation : Le client inclut le JWT dans les en-têtes des requêtes ultérieures vers le
serveur. Le serveur peut alors vérifier la signature du JWT et extraire les informations
de l'utilisateur de la charge utile pour accorder l'accès aux ressources protégées.

Figure 1: Diagramme de fonctionnement des JWT (source docs.spring.io)

1. Le filtre d'authentification, lors de la lecture du jeton Bearer, transmet un jeton


BearerTokenAuthentication à l'AuthenticationManager, qui est mis en œuvre par
ProviderManager.
2. Le ProviderManager est configuré pour utiliser un AuthenticationProvider de type
JwtAuthenticationProvider.
3. JwtAuthenticationProvider décode, vérifie et valide le JWT à l'aide d'un JwtDecoder.
4. JwtAuthenticationProvider utilise ensuite le JwtAuthenticationConverter pour
convertir le Jwt en une collection d'autorisations accordées.
5. Lorsque l'authentification réussit, l'authentification retournée est de type
JwtAuthenticationToken et a un principal qui est le Jwt retourné par le JwtDecoder
configuré. En fin de compte, le JwtAuthenticationToken retourné est défini sur
SecurityContextHolder par le filtre d'authentification.
Les avantages des JWT incluent les suivants :

 Compacts : Les JWT sont compacts et peuvent être envoyés en tant que paramètres
d'URL, dans un en-tête HTTP ou dans des cookies.
 Auto-suffisants : Le jeton contient toutes les informations nécessaires, réduisant ainsi
le besoin d'interroger une base de données pour les informations de l'utilisateur.
 Décentralisés : Étant donné que les JWT sont auto-suffisants, le serveur n'a pas besoin
de conserver des informations de session, ce qui facilite la mise à l'échelle et la
distribution des applications.
En ce qui concerne les considérations de sécurité, les JWT sont signés numériquement, mais
ils ne sont pas chiffrés. Les informations qu'ils contiennent peuvent être décodées par
quiconque a accès au jeton, mais la signature garantit son intégrité. Il n'est pas recommandé
de stocker des données sensibles dans la charge utile, car celle-ci peut être facilement
décodée.
Pour éviter toute altération, il est important d'utiliser des algorithmes de signature forts et
sécurisés pour signer les jetons. Les secrets utilisés pour la signature doivent être conservés de
manière sécurisée. En cas d'utilisation de la cryptographie à clé publique, la clé privée doit
être gardée secrète.
Les JWT sont largement utilisés pour construire des mécanismes d'authentification et
d'autorisation sécurisés dans les applications web modernes, les API et les systèmes de
connexion unique (SSO).
Voici comment JWT et Spring Security peuvent être intégrés :

 Configuration des dépendances : Tout d'abord, vous devez ajouter les dépendances
nécessaires à votre projet. La configuration de construction de votre projet devrait
inclure Spring Security et les bibliothèques liées à JWT.
 Configuration de l'authentification et de l'autorisation : Configurez Spring Security
pour gérer l'authentification et l'autorisation. Cela implique la mise en place de règles
de sécurité, de fournisseurs d'authentification et de services de détails utilisateur. Vous
pouvez définir les chemins nécessitant une authentification et les rôles requis pour
accéder à certaines ressources.
 Génération et validation des jetons : Implémentez la logique pour générer et valider les
JWT. Spring Security fournit des filtres et des classes pour gérer l'authentification
basée sur les jetons. Vous devez créer un mécanisme pour générer des JWT après une
authentification réussie et valider les JWT entrants pour les requêtes autorisées.
 Filtres de traitement des jetons : Utilisez les filtres Spring Security pour intercepter les
requêtes et effectuer des vérifications d'authentification et d'autorisation. Vous
pourriez implémenter un filtre qui examine le JWT entrant, le valide et configure le
contexte de sécurité si le jeton est valide.
 Détails de l'utilisateur et autorisations : Extrayez les détails de l'utilisateur et les
autorisations de la charge utile du JWT après une validation réussie du jeton. Ces
détails peuvent être utilisés pour peupler le contexte d'authentification de Spring
Security, vous permettant de contrôler l'accès en fonction des rôles et des autorisations
de l'utilisateur.
 Personnalisation des fournisseurs d'authentification : Selon vos besoins
d'authentification, vous pourriez avoir besoin d'implémenter des fournisseurs
d'authentification personnalisés pour valider les JWT par rapport à vos services
backend ou bases de données utilisateur.
 Configuration du contrôle d'accès : Définissez des règles de contrôle d'accès à l'aide de
la configuration de Spring Security. Vous pouvez spécifier les rôles nécessaires pour
accéder à différents points de terminaison ou ressources. Les rôles et autorités peuvent
être dérivés de la charge utile du JWT.
 Gestion des exceptions : Implémentez la gestion des exceptions pour les cas où la
validation du JWT échoue ou lorsque l'accès non autorisé est tenté. Personnalisez les
réponses d'erreur en fonction du contexte de sécurité.
 Déconnexion et expiration des jetons : Pour une sécurité améliorée, gérez l'expiration
des jetons et implémentez un mécanisme de déconnexion. Les JWT peuvent avoir un
temps d'expiration spécifié dans leur charge utile.
 Tests et documentation : Testez soigneusement votre implémentation de sécurité
Spring basée sur JWT. Fournissez également une documentation claire pour les
développeurs travaillant avec le système de sécurité.
Maintenir à jour les bibliothèques Spring Security et JWT est important car leurs API et
meilleures pratiques évoluent. La documentation officielle de Spring Security ainsi que les
ressources en ligne fournissent souvent des guides détaillés sur l'intégration de
l'authentification et de l'autorisation basées sur JWT.
Ce chapitre présente un exemple montrant comment sécuriser une API REST à l'aide de JWT
avec Spring Security 6, Spring Boot 3+ et PostgreSQL. Tout d'abord, téléchargez et installez
PostgreSQL depuis https://www.postgresql.org/download/windows/
Ensuite, créez une nouvelle base de données nommée "jwtsecuritydb". Le nom d'utilisateur
est "postgres" et le mot de passe est "postgres".
Figure 2: Notre nouvelle base de données PostgreSQL est opérationnelle.

Ensuite, créez un nouveau projet Spring nommé "JWT_Security_Authentication" en utilisant


l'outil web Spring Initializr disponible sur https://start.spring.io/, comme illustré dans la
figure.

Figure 3: Nouveau projet Spring en utilisant Spring Initializr

Cet exemple utilise Java 20, Maven et JAR, avec Spring Web, le pilote PostgreSQL, Spring
Security, Spring Data JPA et Lombok en tant que dépendances.
La structure de fichiers du projet est illustrée dans la figure.
Figure 4: New Spring project structure

Vous aimerez peut-être aussi