(V14.4.2)


La révocation de jetons JWT par le serveur de ressources (application exposant les webapis REST) est un élément de sécurisation.
Un jeton dont l'utilité est devenue caduque alors que sa durée de validité n'est pas révolue doit être révoqué. Ainsi il ne peut être utilisé pour s'authentifier malicieusement auprès d'un service
.
L'opération de révocation est réalisée par le biais d'une requête explicite à une webapi dédiée.

Note/mise en garde : l'implémentation de la révocation des jetons par le serveur de ressources casse le paradigme d’une application stateless scalable. Les informations de révocation ne sont pas partageables entre deux instances de l'application.

1. Configuration de la gestion de révocation

La gestion de la révocation n'est pas active par défaut. Pour la rendre opérationnelle, il faut déclarer - dans le fichier Beans.xml - un bean de type JwtRevokeConfiguration

<bean id="jwtTokensRevocation" class="com.hardis.adelia.webservice.JwtRevokeConfiguration" init-method="loadTokensMap" destroy-method="saveTokensMap" />
      
ou 

<bean id="jwtTokensRevocation" class="com.hardis.adelia.webservice.JwtRevokeConfiguration" init-method="loadTokensMap" destroy-method="saveTokensMap">
      <property name="jwtClaimId"               value="???"/> <!-- default value: jti -->
      <property name="jwtPurgeFrequencyTime"    value="???"/> <!-- default value: 3600 -->        
</bean>

2. Webapis

Purpose

Api Endpoint

HTTP Verb

Response

Status 

Revocation

 

/<ContextPath>/<CXFServletPath>/tokens/revocation

@DELETE 

Media-type : text/plain
Values : t
rue | false 

200 
401
404 

Is a token revoked ?

 

/<ContextPath>/<CXFServletPath>/tokens/revocation/{jwtId}

 

@GET 

Media-type : text/plain
Values : t
rue | false

 

200
401

404 

Revoked tokens list

/<ContextPath>/<CXFServletPath>/tokens/revocation/list

 

@GET 

Media-type : application/json

[ { "
jwtId": "TokenId__FE706DC72E90060E9E88FB887ACB72E1_25_1619685311434", "revokedBy": "userName", "revocationRequestDate": "2021-04-29T08:35Z", "expirationDate": 1619688911 }, { "jwtId": "TokenId__FE706DC72E90060E9E88FB887ACB72E1_28_1619685265807", "revokedBy": "userName", "revocationRequestDate": "2021-04-29T08:35Z", "expirationDate": 1619688865 } ] 

200
401
 
404 

 

HTTP Code :  

(V14.9.0)

Ajout d'une implémentation "distribuée" de la révocation des jetons JWT à l'aide de NATS/JetStream.
Si au moins un serveur Nats est défini et qu'une connexion à celui-ci est établie alors le mode distribué est activé (sous condition de la création réussie ou de l'existence du stream et du sujet).
Dans ce mode chaque demande de révocation émet un message dans le sujet ${jwtNatsSubject} du stream ${jwtNatsStreamName}. Les messages sont conservés dans le stream pour la durée définie par ${jwtNatsStreamMaxAge}.
Le message est une chaine au format UTF-8 composée de 4 champs délimités par le caractère ; → Exemple : <JwtId>;<RevokedBy>;<RevocationRequestDate>;<TokenExpirationDate>

<bean id="jwtTokensRevocation" class="com.hardis.adelia.webservice.JwtRevokeConfiguration" init-method="loadTokensMap" destroy-method="saveTokensMap">
	<property name="jwtNatsServers" 		value="localhost:4222"/> <!-- si un ou plusieurs serveurs sont définis alors le mode partagé est activé sous condition d'une connexion réussie à l'un des serveurs -->
	<property name="jwtNatsStreamName"		value="ADELIASTREAM"/> <!-- Nom du stream dédié ; défaut : "ADELIASTREAM" -->
	<property name="jwtNatsSubject"    		value="streaming.adelia.internal.jwt.revoke"/> <!-- Nom du sujet ; défaut : "streaming.adelia.internal.jwt.revoke" -->
	<property name="jwtNatsStreamMaxAge" 	value="12"/> <!--en heures, âge maximal des messages dans le stream - valeur à fixer au regard de la durée de vie des jetons ; défaut: "24"-->
    
    <!-- Nats authentication : nkey -->
    <property name="jwtNatsAuthNKeySeed" value="CRYPT(00D133D32D285115D308A5E89F9CEA80D227FDB3304CBD18AD596D09AA40359D7F3DA0F74CCDE20B8A6BD53687A2584851712091A26207A7F7D790DD719753E7D7)"/>
</bean>

Authentification au serveur Nats :


(V14.10.0)

Possibilité de préciser une liste de noms de claim pour la propriété jwtClaimId : utiliser le ; comme séparateur.
Le jeton est identifié par le premier nom de claim de la liste valide pour le jeton.

<bean id="jwtTokensRevocation" class="com.hardis.adelia.webservice.JwtRevokeConfiguration" init-method="loadTokensMap" destroy-method="saveTokensMap">
...
      <property name="jwtClaimId"               value="jti;tid"/> <!-- liste des noms de claim pouvant identifier le jeton -->
...
</bean>