La classe du runtime Adélia RsJWTAuthenticationFilter assure l'authentification des requêtes adressées au serveur de ressources via la validation d'un jeton JWT.
Cette validation est configurable via le bean jwtTokenConfiguration du fichier beans.xml. Cette configuration permet notamment de définir :

  • l'URL pattern des ressources devant être sécurisées
  • définir la durée de validité du token
  • définir le nom du claim portant la liste des rôles du user
  • définir l'audience du token
  • définir un (ou des) segment(s) d'URL de passthrough pour swagger.

La validation du jeton requiert également une clé publique (ou un secret) pour valider la signature numérique du jeton.
De façon standard, les jetons délivrés par la servlet JWTServlet sont signés avec l'algorithme de chiffrement RSA256.

Côté serveur de ressources, l'accès à la clé publique pour la validation de la signature est renseigné via la ressource jdni nommée "url/adelRSJwtSecurity".
Les informations connexes à la clé publique (type du keystore, algorithme de chiffrement, alias, password, secret...) sont renseignées par défaut.

Il est néanmoins possible - dans le cadre de la validation d'un jeton émis par un tiers - de modifier cette configuration à l'aide des propriétés suivantes (les noms des propriétés sont à rapprocher de celles utilisées par la librairie CFX/JOSE) :

<bean id="jwtTokenConfiguration" class="com.hardis.adelia.webservice.JwtTokenConfiguration">
   <property name="jwtAuthScheme" value="JWT"/>
	<.../>
    <property name="jwtSecKeyFileName"  value="???" />  <!-- JOSE : rs.security.keystore.file ; Nom de fichier ou nom d une ressource JNDI permettant d accéder au truststore. Défaut:url/adelRSJwtSecurity -->
	<property name="jwtSecKeyStoreType"  value="???" /> <!-- JOSE : rs.security.keystore.type ; Type de store : jks=défaut -->
	<property name="jwtSecKeyStoreAlias" value="???"/>  <!-- JOSE : rs.security.keystore.alias; Alias du truststore -->
	<property name="jwtSecKeyStorePwd"   value="???"/>  <!-- JOSE : rs.security.keystore.password; mot de passe d'accès au truststore -->
	<property name="jwtSecKeySignAlg"    value="???"/>  <!-- JOSE : rs.security.signature.algorithm -->
</bean>

La propriété jwtSecKeyStoreType n'est configurable qu'à partir de la version 14 d'Adélia studio.
La propriété jwtSecKeyFileName n'est configurable qu'à partir de la version 14.1.1 d'Adélia studio.
La propriété jwtSecKeysignAlg n'est configurable qu'à partir de la version 14.6.0 d'Adélia studio. Permet d'imposer un algorithme de chiffrement pour la validation de la signature. Valeurs possibles : RS256 | RS384 | RS512

La propriété jwtSecKeyStoreAlias peut - à partir de la version 14.1.1 d'Adélia studio - prendre plusieurs valeurs séparées par un ; .
Exemple : 

<property name="jwtSecKeyStoreAlias" value="alias1;alias2"/>
La signature du jeton pour alors être validée par différents certificats stockés dans le truststore (utile si différents jetons - émis par différentes sources - doivent être acceptés).

Il peut alors être nécessaire de définir des noms de claim (JwtUserPrincipalClaim et jwtUserRoleClaim) spécifiques à chaque type de jeton (donc à chaque alias). Cela est possible avec la syntaxe suivante : 

<property name="jwtSecKeyStoreAlias" value="alias1[user=sub,role=roles];alias2[user=preferred_username,role=realm_access.roles]"/>

Pour rappel :

  • JwtUserPrincipalClaim est le claim portant le nom du user authentifié.
  • jwtUserRoleClaim est le claim portant les rôles du user authentifié.


La propriété jwtSecKeyFileName (→ CXF/JOSE : rs.security.keystore.file) prend par défaut la valeur (ressource JNDI) "url/adelRSJwtSecurity".
Si cette ressource JNDI n'est pas trouvée, le fichier /WEB-INF/Conf/RSJwtSecurity.key est utilisé.


(V14 PTF7 Fix04) Validation de la signature d'un jeton JWT à partir d'une JWK (JSON Web Key) contenue dans un JWKS (JWK Set).

Il est possible de valider la signature d'un jeton JWT à l'aide d'une JSON Web Key (JWK) contenue dans un JWKS (JWK Set : document JSON contenant un ensemble de JSON Web Keys).

  • Principe de la validation de la signature à l'aide d'un JWKS


    La validation d'un jeton JWT via un JWKS repose sur la recherche d'une clé publique (ou d'un secret) dans un document JSON (local ou distant) à partir des informations iss et kid contenues dans le jeton.
    iss définit le trusted issuer. Cet  issuer permet d'identifier le fournisseur de confiance et d'en récupérer le JWKS dans le cas d'un document distant ; cet issuer peut avoir une valeur quelconque (mais non vide) dans le cas d'un JWKS local.
    kid identifie la clé (key id) au sein du JWKS. Les clés sont typées au regard d'une classe d'algorithme de chiffrement.

    Exemple de JWKS :

    JWKS
    {"keys":
           [
             {"kty":"EC",
              "crv":"P-256",
              "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
              "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
              "use":"enc",
              "kid":"1"},
    
             {"kty":"RSA",
              "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
              "e":"AQAB",
              "alg":"RS256",
              "kid":"2011-04-29"}
           ]
         }
  • Validation au regard d'un JWKS distant lié à un fournisseur de confiance (trusted issuer).

    Ce fournisseur de confiance - identifié par une URI - donne accès à une configuration OpenID standardisée via l'adjonction du segment d'URI "/.well-known/openid-configuration" : la propriété  jwks_uri indique l'URL du JWKS.
    La propriété jwkTrustedIssuers porte le nom d'un ou plusieurs fournisseurs de confiance (trusted issuers). Dans le cas d'une liste de fournisseurs, utiliser le caractère ; comme séparateur.
    Dans le cas où les valeurs par défaut des noms des claims permettant de récupérer l'utilisateur authentifié d'une part et ses rôles d'autre part (respectivement sub et roles) ne seraient pas adaptées, il est possible de spécifier d'autres valeurs.
    L'adjonction d'un attribut user au fournisseur de confiance (trustedIssuer[user=userclaim]) permet de surcharger le nom du claim permettant de récupérer l'utilisateur authentifié.
    L'adjonction d'un attribut role au fournisseur de confiance (trustedIssuer[role=roleclaim]) permet de surcharger le nom du claim permettant de récupérer les rôles de l'utilisateur authentifié.
    Possibilité de réactualiser le JWKS d'un fournisseur de confiance suite à un échec de validation : la propriété jwkJWKSUpdateOnSignCheckFail permet de forcer la réactualisation du JWKS suite à un échec de validation de signature.

Exemple 1 : Déclaration d'un fournisseur de confiance.
JWKS distant accessible via la valeur associée à la propriété jwks_uri du document de configuration disponible via la ressource https://auth.dev.hardis-group.com/auth/realms/adelia/.well-known/openid-configuration
Le JWKS n'est pas réactualisé si jamais la vérification de la signature échoue.

Validation via un fournisseur de confiance / JWKS distant
<bean id="jwtTokenConfiguration" class="com.hardis.adelia.webservice.JwtTokenConfiguration">
   ...
   <property name="jwkTrustedIssuers" value="https://auth.dev.hardis-group.com/auth/realms/adelia"/>
</bean> 

Exemple 2 : Déclaration de 2 fournisseurs de confiance avec surcharge des claims sub et roles pour le second.
Utilisation du claim 'preferred_username' pour la récupération du nom de l'utilisateur authentifié
Utilisation du claim 'realm_access.roles' pour la récupération des rôles de l'utilisateur authentifié
Le JWKS est réactualisé suite à l'échec de la vérification de la signature.

Validation via 2 fournisseurs de confiance / JWKS distants avec redéfinition des claims 'role' et 'user'
<bean id="jwtTokenConfiguration" class="com.hardis.adelia.webservice.JwtTokenConfiguration">...
   ...   
   <property name="jwkTrustedIssuers" value="https://auth.dev.hardis-group.com/auth/realms/adelia;https://auth.dev.hardis-group.com/auth/realms/reflex[user=preferred_username,role=realm_access.roles]"/>
   <property name="jwkJWKSUpdateOnSignCheckFail" value="true"/> <!-- default : false -->
</bean> 
  • Validation au regard d'un JWKS local.

    Il est possible de valider un jeton au regard d'un JWKS local : le fichier contenant les clés est placé dans le répertoire WEB-INF/conf de la webapp ou est accessible via une ressource JNDI.
    La propriété jwkFileName porte le nom du fichier ou le nom de la ressource JNDI.
    Dans le cas où les valeurs par défaut des noms des claims permettant de récupérer l'utilisateur authentifié d'une part et ses rôles d'autre part (respectivement sub et roles) ne seraient pas adaptées, il est possible de spécifier d'autres valeurs.
    La propriété jwkUserPrincipalClaim permet de surcharger le nom du claim permettant de récupérer l'utilisateur authentifié.
    La propriété jwkUserRoleClaim permet de surcharger le nom du claim permettant de récupérer les rôles de l'utilisateur authentifié.
    Remarque : pour une validation via un JWKS local le jeton doit toujours contenir les deux claims issuer et kid mais dans ce cas le issuer peut avoir une valeur quelconque (mais non vide).

    Exemple 1 : JWKS nommé certs.json placé dans le répertoire WEB-INF/conf de la webapp. Utilisation du claim 'preferred_username' pour la récupération du nom de l'utilisateur authentifié.
Validation via un JWK set local
<bean id="jwtTokenConfiguration" class="com.hardis.adelia.webservice.JwtTokenConfiguration">
   ...
   <property name="jwkFileName" value="certs.json"/>
   <property name="jwkUserPrincipalClaim" value="preferred_username"/>
</bean> 

Exemple 2 : JWKS accédé via une ressource JNDI nommée url/jwks. Utilisation du claim 'realm_access.roles' pour la récupération des rôles de l'utilisateur authentifié.

Validation via un JWK set local
<bean id="jwtTokenConfiguration" class="com.hardis.adelia.webservice.JwtTokenConfiguration">
   ...
   <property name="jwkFileName" value="url/jwks"/>
   <property name="jwkUserRoleClaim" value="realm_access.roles"/>
</bean> 

La ressource JNDI doit alors être correctement définie dans le fichier server.xml de la configuration tomcat de la webapp.

Exemple (ressource pointant sur le fichier externalisé "c:\conf\restapp\certs.json" :
<Resource auth="Container" factory="com.hardis.common.JndiURLFactory" name="url/jwks" type="java.net.URL" url="file:///c:/conf/restapp/certs.json"/>


  • Chaînage de la validation
    - Il est possible de chainer une validation via un JWKS local puis via un JWKS distant en fixant les 2 propriétés jwkFileName et jwkTrustedIssuers.
    - Il est possible de définir conjointement une validation à base de JWK et d'un truststore JKS.
    Si une configuration JWK est définie et que le jeton contient les claims iss (issuer) et un kid  (keyid) alors la validation commence par une validation de type JWK (recherche du JWKS local et/ou celui du fournisseur de confiance).
    En cas d'échec de cette validation et si une configuration de type JKS existe, une tentative de validation via le truststore est réalisée.


  • Aucune étiquette