Téléchargement des produits


Version anglaise


 

La révocation de jetons JWT par le serveur de ressources est un élément supplémentaire 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 pas ê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.
Adélia Studio propose deux implémentations de révocation de jeton :

  • Implémentation simple pour un serveur unique de ressources.
  • Implémentation distribuée (plusieurs serveurs de ressources et/ou applications tierces devant être informées des jetons révoqués). Cette implémentation repose sur le broker de messages Open Source Nats/Jetstream.

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.


Mode simple
jwtRevokeConfiguration - Exemple : implémentation mono serveur de ressources
<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>


  • jwtClaimId : Nom du claim identifiant le jeton JWT. Valeur par défaut : "jti". Cette information est utile uniquement dans le cas où l'on souhaite savoir si un jeton, identifié par son id, a été révoqué.
  • jwtPurgeFrequencyTime : Fréquence de purge, en secondes, de la table des jetons révoqués. Valeur par défaut : 3600. A adapter en fonction de la durée de la validité des jetons.

Mode distribué

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 chaîne au format UTF-8 composée de quatre champs délimités par le caractère ; → Exemple : <JwtId>;<RevokedBy>;<RevocationRequestDate>;<TokenExpirationDate>

  • <JwtId> : String> → Id du jeton
  • <RevokedBy> : String → Nom de l'utilisateur à l'initiative de la révocation (→ 'sub' du jeton utilisé lors de la révocation)
  • <RevocationRequestDate> : String ; ISO-8601→ Date de la demande révocation.
  • <TokenExpirationDate> : Long → Date (unix time) d'expiration prévue du jeton.
jwtRevokeConfiguration - Exemple : implémentation distribuée
<bean id="jwtTokensRevocation" class="com.hardis.adelia.webservice.JwtRevokeConfiguration" init-method="loadTokensMap" destroy-method="saveTokensMap"> 
   <property name="jwtClaimId" value="???"/> <!-- default value: jti -->
   <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>
  • jwtClaimId : Nom du claim identifiant le jeton JWT. Valeur par défaut : "jti". Cette information est utile uniquement dans le cas où l'on souhaite savoir si un jeton, identifié par son id, a été révoqué.
  • jwtNatsServers : Nom du serveur Nats ou noms des serveurs Nats (séparés par un ;  → exemple: srvnats1:4222;srvnats2:4222).
  • jwtNatsStreamName : Nom du stream dédié [défaut : ADELIA_JWT_TOKEN_STREAM].
  • jwtNatsSubject : Nom du sujet utilisé pour la révocation des jetons [défaut : streaming.adelia.internal.jwt.revoke].
  • jwtNatsStreamMaxAge : Age maximal des messages dans le stream dédié. Cet âge doit être supérieur à la durée de vie des jetons, ainsi un nouveau client/abonné prend connaissance de tous les jetons révoqués possiblement actifs.


Authentification au serveur Nats

  • User/Password
    jwtNatsAuthUser : Nom de l'utilisateur
    jwtNatsAuthPwd : Mot de passe. Pour chiffrer le mot de passe utilisez la commande "java EncryptPassword" du runtime Adélia, et indiquez le mot de passe entre parenthèses préfixé par "CRYPT".
    → exemples :

    <property name="jwtNatsAuthUser" value="bob"/>
    <property name="jwtNatsAuthPwd" value="s3cr3t"/>

    <property name="jwtNatsAuthUser" value="bob"/>
    <property name="jwtNatsAuthPwd" value="CRYPT(0040B783FDB007E032)"/>

  • Token
    jwtNatsAuthToken : Pour chiffrer le token utilisez la commande "java EncryptPassword" du runtime Adélia, et indiquez le mot de passe entre parenthèses préfixé par "CRYPT".
    → exemples :
    <property name="jwtNatsAuthToken" value="s3cr3t"/>
    <property name="jwtNatsAuthToken" value="CRYPT(0040B783FDB007E032)"/>

  • Nkey
    jwtNatsAuthNKeySeed : clé privée. Pour chiffrer la clé utilisez la commande "java EncryptPassword" du runtime Adélia, et indiquez le mot de passe entre parenthèses préfixé par "CRYPT".
    → exemples :
    <property name="jwtNatsAuthNKeySeed" value="SUAFGCEVJB6DTYFPEQIC4DSLGBRSD75BMQPO2HS6SX4FNPVZDTHMQYYN24"/>
    <property name="jwtNatsAuthNKeySeed" value="CRYPT(00D133D32D285115D308A5E89F9CEA80D227FDB3304CBD18AD596D09AA40359D7F3DA0F74CCDE20B8A6BD53687A2584851712091A26207A7F7D790DD719753E7D7)"/>

  • Credentials file

    jwtNatsAuthCredsFile : emplacement du fichier contenant les informations d'authentification. Cf. https://docs.nats.io/using-nats/developer/connecting/creds

    → exemple :
    <property name="jwtNatsAuthCredsFile" value="nats.creds"/>

Qui a le droit de révoquer un jeton ?

Le jeton peut être révoqué uniquement par une requête authentifiée par ce même jeton.


Persistance de la table des jetons révoqués

La table des jetons révoqués subsiste après un redémarrage du serveur de ressources.


Purge de la table des jetons révoqués

La table des jetons révoqués est purgée à une fréquence donnée (par défaut, toutes les heures. Cf. jwtPurgeFrequencyTime). Les jetons révoqués purgés sont les jetons révoqués arrivés à expiration.

↑ Haut de page


Webapis

Objectif
Point d'accès de l'API
Verbe HTTP
Réponse
Statut 

Révocation


/<ContextPath>/<CXF_url-pattern>/tokens/revocation

@DELETE 

Media-type : text/plain
Valeurs : true | false 

200 
401
404 

Est-ce que le jeton jwtId est révoqué ?


/<ContextPath>/<CXF_url-pattern>/tokens/revocation/{jwtId}


@GET 

Media-type : text/plain
Valeurs : true | false


200
401
404

Liste des jetons révoqués

/<ContextPath>/<CXF_url-pattern>/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 :  

  • Si l'opération aboutit : HTTP Code = 200

  • Si l'opération échoue car la requête de révocation n'est pas autorisée : HTTP Code = 401

  • Si le bean JwtRevokeConfiguration n'est pas déclaré (= révocation non active) ou si le jeton interrogé n'est pas trouvé : HTTP Code = 404.


Exemple de révocation d'un jeton - Code Adélia
EXECUTER_HTTP *URL('http://monsite/mawebapp/ws/tokens/revocation') *OPTIONS('--request DELETE --header Accept: text/plain --header Authorization:JWT <jwt_token>') *REPONSE(VarRetCode) *CODE_HTTP(VarHttpCode)
Remarque : "<jwt_token>" correspond à la valeur du jeton

↑ Haut de page


  • Aucune étiquette