Spring Boot 4.1.0 a été publié le 10 juin 2026 et apporte quelques nouveautés. Nous nous intéresserons ici à
la nouvelle propriété spring.security.oauth2.resourceserver.jwt.authorities-claim-expressions
qui facilite la récupération des droits (rôles de l’utilisateur) dans les jetons JWT lorsque ceux-ci présentent un peu de complexité.
À propos des jetons JWT et de Spring Link to heading
Un jeton JWT (JSON Web Token) est un moyen de transférer un ensemble propriétés (en anglais claims) entre deux parties via un protocole web (typiquement HTTP) et d’en vérifier l’authenticité à partir d’une signature. Le but du jeton JWT est de permettre à un service de contrôler l’identité et les droits d’un utilisateur qui souhaite accéder à une ressource, l’identité et les droits de l’utilisateur ayant été vérifiés par ailleurs par un service tiers (authorization server dont un exemple est Keycloak) qui a délivré le jeton JWT. Le jeton est constitué de trois parties :
- un en-tête comprenant notamment le type du jeton et l’algorithme utilisé pour la signature (dans le paramètre
alg). - un payload comprenant les propriétés du jeton au format JSON. Un certain nombre de clés sont normalisées mais non obligatoires
sauf visiblement
exp(instant d’expiration du token JWT). Ces propriétés sont variées et permettent de transférer des informations sur l’identité de l’utilisateur (mail, nom, prénom…), ses droits et habilitations ou encore l’audience du token qui désigne le ou les services pour lesquels le jeton a été généré. Il est possible que le JSON ait une structure complexe à plusieurs niveaux et avec des tableaux. Ce qui justifie l’utilisation d’expressions SpEL pour récupérer des habilitations à différents niveaux et/ou différents endroits du payload. - une signature qui correspond à la signature, selon l’algorithme défini dans l’en-tête, du contenu de l’en-tête et du payload encodés en base64 concaténés par un
..
Lors du transport du jeton JWT, les trois parties sont encodées en base 64 et concaténées avec un . (point) en guise de séparateur entre chacune.
Ce qui permet de passer le token dans un en-tête HTTP Authorization.
Lors du décodage du jeton, le serveur de ressource est chargé de décoder et valider le token JWT avant d’en utiliser les informations pour contrôler l’accès de l’utilisateur.
La validation est une étape essentielle afin de s’assurer de l’authenticité du token, elle consiste principalement en :
- la vérification de la signature (à l’aide de la clé publique du serveur d’autorisation lors de l’utilisation d’un algorithme de chiffrement asymétrique)
- la vérification de l’audience du token
- la vérification de la date d’expiration du token
Un exemple de jeton JWT Link to heading
On peut représenter un jeton en clair avec son en-tête et son payload au format json :
- en-tête :
{
"typ": "JWT",
"alg": "RS256"
}
- payload :
{
"exp": 1781602479,
"iat": 1781602179,
"auth_time": 1781588556,
"iss": "https://example.com/auth/realms/accounts",
"aud": ["green-app", "blue-app"],
"typ": "Bearer",
"realm_access": {
"roles": ["manager_BLUEAPP", "access-granted_FORGE"]
},
"resource_access": {
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
"scope": "openid profile email",
"email_verified": false,
"name": "Fabrice Bibonne",
"preferred_username": "FBibonne",
"given_name": "Fabrice",
"family_name": "Bibonne",
"email": "fabrice.bibonne@courriel.eco"
}
Dans ce cas, le jeton sera signé par un algorithme à chiffrement asymétrique (RSA) si bien que la vérification se fera simplement par le serveur de ressources à partir de la clé publique du serveur d’autorisation.
Spring dans tout ça Link to heading
La gestion des jetons JWT pour le serveur de ressources se fait côté Spring Security dans le module spring-security-oauth2-jose dont dépend le module spring-boot-starter-security-oauth2-resource-server.
Spring Security a la responsabilité de récupérer le token JWT dans la requête HTTP entrante, de le décoder (désérialisation + validation) et d’en tirer les informations utiles pour enrichir le principal
de la requête HTTP à traiter. Ces opérations peuvent être pénibles à réaliser manuellement, c’est pourquoi l’apport du framework est essentiel.
Comment utiliser spring.security.oauth2.resourceserver.jwt.authorities-claim-expressions ?
Link to heading
Sous le capot Link to heading
Spring Security traduit les jetons JWT en tant qu’instances de org.springframework.security.oauth2.jwt.Jwt pour pouvoir les traiter.
C’est sur ces objets que devront porter les expressions SpEL chargées de récupérer les
habilitations dans les tokens JWT. Les claims du premier niveau de l’objet Jwt peuvent être récupérés à travers une Map fournie par Jwt::getClaims. En revanche, les claims des niveaux
inférieurs peuvent être du type com.nimbusds.jose.shaded.gson.JsonElement (nimbus-jose-jwt est la librairie sous-jacente sur laquelle repose spring-security-oauth2-jose pour le décodage des jetons JWT).
Les types JsonElement ne supportent pas les syntaxes SpEL pour les types indexés (notation element[index]). C’est pouquroi il vaut mieux utiliser des méthodes get supportées à la fois par les Map
et JsonElement pour naviguer dans le graphe du JSON du payload.
La propriété spring.security.oauth2.resourceserver.jwt.authorities-claim-expressions permet d’instancier un ou plusieurs objets de type
org.springframework.security.oauth2.server.resource.authentication.ExpressionJwtGrantedAuthoritiesConverter :
une nouvelle instance de ExpressionJwtGrantedAuthoritiesConverter est créée automatiquement par Spring Boot pour chaque expression SpEL lors de la configuration de la couche de contrôle d’accès
de Spring Security OAuth2. Spring Boot configure Spring Security de sorte que les différentes expressions SpEL sont mobilisées pour chaque JWT à décoder.
Chaque expression SpEL doit être correctement formée sinon l’application ne démarre pas. Chaque expression est ensuite appliquée sur la Map résultant de Jwt::getClaims et doit retourner une collection de droits
(castable en une Collection<String>). L’application d’un expression SpEL se fait à l’aide de la méthode org.springframework.expression.Expression#getValue(java.lang.Object, java.lang.Class<T>) où l’objet root est la Map des claims
et le type cible java.util.Collection<?>. Si l’application de l’expression échoue, l’exception est silencieusement traitée (loguée en trace) et une liste vide de droits est retournée.
Écrire une expression SpEL pour récupérer une collection de droits Link to heading
Qu’est ce que le SpEL ? Link to heading
Spring Expression Language (SpEL) est un expression language dont la syntaxe est proche de java qui permet d’écrire des expressions pouvant s’appliquer à un contexte (éventuellement sur un ensemble d’objets) et de retourner une valeur. Il permet de manipuler des objets java, appeler des méthodes du JDK ou bien des méthodes définies par l’utilisateur (statiques ou non). Dans un contexte Spring, il permet également de manipuler les beans du contexte applicatif. Les expressions sont passées au programme sous forme de chaînes de caractères et interprétées à l’exécution.
Qualités d’une expression SpEL pour traiter un JWT Link to heading
Dans le cas de la récupération des habilitations pour un token JWT, l’expression SpEL portera sur les claims du token JWT, c’est-à-dire un objet de type Map<String, Object> (retour de Jwt::getClaims)
et doit retourner une collection de droits (castable en une Collection<String>). Le premier niveau de claims étant une Map, il est possible d’utiliser l’opérateur d’indexation des Map
pour récupérer la valeur à partir du nom de la clé. Par exemple : #root['roles'] (#root désigne la Map en entrée : il n’est pas obligatoire de le mentionner).
Les niveaux inférieurs pouvant être des objets
de type com.nimbusds.jose.shaded.gson.JsonElement, il est préférable d’utiliser des noms de méthodes qui fonctionnent aussi bien sur ces objets que sur des Map à savoir la méthode get pour obtenir
une valeur à partir d’une clé.
Enfin, la collection retournée doivent être de type java.util.Collection<String> : les éléments des collections peuvent être transformés à cette fin en utilisant
l’opérateur de projection de SpEL. Par exemple : get('roles').![toString()]
Ces différentes opérations sont chainable dans une même expression SpEL.
Exemple d’expressions SpEL Link to heading
Pour récupérer les habilitations dans resource_access.account.roles dans l’exemple ci-dessus
Link to heading
get('resource_access').get('account').get('roles').![toString()]
Pour récupérer les habilitations dans groups et retirer les suffixes dans l’exemple ci-dessus
Link to heading
['realm_access'].get('roles').![toString()].![substring(0, #this.indexOf('_'))]
Renseigner la liste des expressions SpEL dans la propriété spring.security.oauth2.resourceserver.jwt.authorities-claim-expressions
Link to heading
Afin que les éventuelles virgules dans les expressions SpEL ne soient pas confondues avec un délimiteur de liste par le parseur de propriétés,
il est préférable de définir authorities-claim-expressions sous la forme d’un tableau
Cas d’un fichier application.yaml
Link to heading
spring:
security:
oauth2:
resourceserver:
jwt:
authorities-claim-expressions:
- "get('resource_access').get('account').get('roles').![toString()]"
- "['groups'].![toString()].![substring(0, #this.indexOf('_'))]"
Cas d’un fichier application.properties
Link to heading
spring.security.oauth2.resourceserver.jwt.authorities-claim-expressions[0] = get('resource_access').get('account').get('roles').![toString()]
spring.security.oauth2.resourceserver.jwt.authorities-claim-expressions[1] = ['groups'].![toString()].![substring(0, #this.indexOf('_'))]
Aucun code supplémentaire n’est nécessaire Link to heading
La présence du module spring-boot-starter-security-oauth2-resource-server et des propriétés suffisent à Spring Boot pour charger automatiquement la configuration de Spring Security OAuth2
pour le serveur de ressources. Les propriétés suivantes seront probablement nécessaires :
spring.security.oauth2.resourceserver.jwt.jwk-set-uri: obligatoire (ou sinonspring.security.oauth2.resourceserver.jwt.issuer-uri)spring.security.oauth2.resourceserver.jwt.authority-prefix: facultatif mais sans valeur, les habilitations tirées du JWT seront automatiquement préfixées parSCOPE_spring.security.oauth2.resourceserver.jwt.audiences: recommandé pour vérifier que le jeton JWT est utilisé pour le bon service
Écrire un test pour les expressions SpEL Link to heading
Les expressions SpEL ne sont compilées et vérifiées qu’à l’exécution et rien ne garantie donc qu’elles seront correctes : c’est pourquoi il est préférable d’écrire un ou plusieurs tests pour
vérifier qu’elles compilent et qu’elles correspondent bien à la structure du jeton JWT. Voici une proposition de test à cet effet. Le reste du projet contient la configuration
par propriété de l’authentification OAuth2 pour le serveur de ressources à partir du token JWT (fichier src/main/resources/application.yaml), les dépendances mavenr nécessaires et la
classe Main.
Conclusion Link to heading
- Grâce à Spring Boot 4.1 :
- La gestion du contrôle d’accès pour un serveur web par oauth2 via des tokens JWT peut se faire par simple
configuration et sans aucune ligne de code grâce au module
spring-boot-starter-security-oauth2-resource-server - Les droits et habilitations sont récupérées même si la structure du jeton JWT est complexe (plusieurs niveaux de Claims et plusieurs emplacements) à l"aide d’une seule propriété
- La gestion du contrôle d’accès pour un serveur web par oauth2 via des tokens JWT peut se faire par simple
configuration et sans aucune ligne de code grâce au module
- Ce qui fait économiser la création de beans spécifiques comme
JwtAuthenticationConverteret les lignes de code de configuration qui vont avec.