La prise en charge d'un jeton JWT est assurée par la déclaration d'une référence à un objet de type JwtTokenConfiguration dans l'élément <jaxrs:server> du fichier beans.xml :
<jaxrs:server ...> <jaxrs:properties> <entry key="jwtTokenConfiguration"> <ref bean="jwtTokenConfiguration"/> </entry> </jaxrs:properties> </jaxrs:server>
L'objet JwtTokenConfiguration expose différentes propriétés liées à l'utilisation du jeton :
<bean id="jwtTokenConfiguration" class="com.hardis.adelia.webservice.JwtTokenConfiguration"> <!-- Authentication scheme ; ex : value ="JWT" ; Authorization: JWT Header.Payload.Signature --> <property name="jwtAuthScheme" value="JWT"/> <!-- Token validation URL pattern --> <property name="jwtBasePath" value="/ws/*"/> <!-- Enable confidential transport (default:false) --> <property name="jwtConfidential" value="false"/> <!-- Swagger URI resources listing authentication passthrough --> <property name="jwtSwaggerURI" value="/ws/api-docs;/ws/swagger*;/ws/openapi*"/> <!-- TimeToLeave value (s) for iat token validity checking --> <property name="jwtTtl" value="3600"/> <!-- ClockOffset value (s) for iat or exp (adjustment) token validity checking --> <property name="jwtClockOffset" value="0"/> <!-- Users roles token claim name --> <property name="jwtUserRoleClaim" value="roles"/> <!-- Enable audience claim validation (default:false)--> <property name="jwtValidateAudience" value="false" /> <!-- Enable confidential transport (default:false) --> <property name="jwtConfidential" value="false"/> </bean>
Description des propriétés :
jwtAuthScheme |
Schéma utilisé dans le header HTTP Authorization pour transmettre le jeton. Par défaut : JWT. Le header HTTP utilisé pour transmettre le jeton suit la syntaxe suivante : "Authorization : <jwtAuthScheme> Token" ou "Authorization : Bearer Token" Exemple : Authorization : JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJoYXJkaXMiLCJpc3MiOiJKV1RQcm92aWRlciIsImlhdCI6MTQ2MzQwMzk2NCwiYXVkIjoiaHR0cDovL2xvY2Fs aG9zdDo4MDgwL2pheHJzIiwianRpIjoiaWRUb2tlbl8xIiwicm9sZXMiOlsiYWRtaW4iLCJ1c2VyIl19.o-qhcj9X-G0np3zxeLt2BSfQxVSMxcCO4AUjSS21m72XD2fC MmQbJmnR86wT_lRIDkWxU0UowcDUOhEUYkmRhhMjN0vPsseWjgcXoj96vJ0X7cTxxpNSpjGmQtyez7IwL3iWkmUtNN-2OlHU4CSzUuj0JNnGfu3dMzC8vum_ E81cT8IJDKxKyTV_NDrQQ2GKx8wGAPC9ZxAi_qBD3UHuFvr70vNEQUVka5azCMMnpAXIoBuZk0oeTPLlTf4rYYCQ7WjsirzSylp8a47Xfgj_e6Qb-J01V9ohD5bgHvv B-fp63vT9dODPz_WKJO37_pdfvJALGIewzec0YU6iJUu5gQ |
jwtBasePath |
Url-pattern définissant l'ensemble des ressources sécurisées par le jeton JWT. Les ressources dont l'URI commence par <ContextPath><jwtBasePath> sont sécurisées via le jeton JWT. Exemple : Si le ContextPath de l'application Web est "/services" et que la valeur de la propriété jwtBasePath est "/ws/*", toutes les ressources dont l'URI commence par /services/ws/ sont sécurisées par le jeton JWT. |
jwtUserRoleClaim | Nom du claim contenant la liste des rôles de l'utilisateur authentifié. Par défaut : roles. |
jwtUserRoleJsonPath |
Si le claim des rôles a pour valeur un document Json, alors jwtUserRoleJsonPath permet de définir un JsonPath indiquant le champ du document qui porte la liste des rôles. Remarque : le jwtUserRoleJsonPath n'est utile que dans le cas où un objet Json est affecté au claim portant les rôles. Exemple : Extrait (Jwt) : "header";: { "alg": "HS256", "typ": "JWT" }, backend: { "roles";: [role1, role2,...] }, frontend: { "roles";: [role1, role2,...] } }, ... } Utilisation du JsonPath "frontend.roles" pour désigner la liste des rôles à utiliser. Extrait (beans.xml) : ... <!-- Users roles JsonPath pattern --> <property name="jwtUserRoleClaim" value="roles"/> <property name="jwtUserRoleJsonPath" value="frontend.roles"/> ... |
jwtTtl |
Durée de vie exprimée en secondes. La durée de vie du jeton est calculée en ajoutant cette valeur à celle du claim prédéfini iat (Issued At). Si le temps actuel dépasse le temps calculé, le jeton n'est plus valide. |
jwtClockOffset |
Décalage horaire exprimé en secondes. Permet de gérer un décalage horaire par rapport au temps défini par l'émetteur du jeton. Ce décalage horaire entre dans le calcul du temps et donc de la validité du jeton pour les claims prédéfinis iat (Issued At), exp (Expiry Time) et nbf (Not Before). |
jwtValidateAudience |
Indique si le claim prédéfini aud doit être validé ou non. Le type de validation à effectuer est lié au type d'audience défini par la propriété jwtAudienceKind. Par défaut : false. |
jwtAudienceKind | Type de validation à effectuer dans le cadre du contrôle du claim aud. Les valeurs possibles sont :
|
jwtConfidential |
Permet de rejeter (value= "true") une requête dont le transport n'est pas sécurisé. Par défaut : false. |
jwtSwaggerURI |
Dérogation pour l'accès à la ressource swagger de listing des services REST. Cette(ces) dérogation(s) permet(tent) à swagger-ui d'accéder au listing des services REST sans avoir à fournir un jeton JWT. La présence du jeton (via le champ [jwt_key]) reste nécessaire pour invoquer les services listés. Exemple : <property name="jwtSwaggerURI" value="/ws/api-docs;/ws/swagger*;/ws/openapi*"/> (Sans jeton, il est possible de récupérer le fichier openapi.json. Il n'est pas possible, en revanche, d'accéder à l'interface de swagger). |
Remarques :
- Les claims prédéfinis iat, exp, nbf sont exclusifs. L'émetteur du jeton choisit le claim prenant en charge la validité temporelle.
- iat [Issued At] : le jeton a été émis à un temps donné.
- exp [ExpiryTime] : le jeton expire à un temps donné.
- nbf [Not Before] : le jeton n'est pas valide avant un temps donné.
- L'émetteur du jeton assigne le nom du client authentifié (utilisateur) dans le claim prédéfini sub. L'utilisation du mot-clé Adélia *USER dans un programme de service REST retourne cette valeur.
- Les rôles du client authentifié (utilisateur) sont listés dans le claim dont le nom est précisé à l'aide de la propriété jwtUserRoleClaim. Ces rôles sont injectés dans le contexte de sécurité de l'application. Dès lors, l'utilisation de la fonction VaToolBxAwsIsUserInRole dans un programme Adélia de service REST permet de savoir si le client est ou n'est pas dans un rôle donné.
Signature numérique du jeton
Pour valider la signature du jeton, la clé de chiffrement doit être accessible via un keystore au format JKS nommé RSJwtSecurity.key.
Ce keystore doit être disponible, soit dans le répertoire WEB-INF/conf de l'application, soit externalisé sous la forme d'une ressource jndi de type URL utilisant la factory com.hardis.adelia.common.URLFactory via l'alias url/adelRSJwtSecurity.
Remarque : un keystore est fourni par défaut dans le répertoire /WEB-INF/conf.