Erreur “New token is expired” lors de la consommation d’objet service-simplicite (le retour)

Bonjour,

nous avons reproduit le cas d’instances clientes implémentant des ObjectServiceSimplicite qui n’arrivent pas à se reconnecter à l’instance servant l’objet métier (cf.
Erreur "New token is expired" lors de la consommation d'objet service-simplicite).

Il s’agit de tokens rejetés par l’instance serveur (code HTTP 401 que le token soit expiré ou pas).

J’ai pu contourner le cas en m’appuyant sur la méthode login(true) de APITool (via getAPIClient) pour forcer un relogin si le search ne ramène rien (je sais, c’est crade :flushed:).

	@Override
	public void postLoad() {
		/*
		 ** DEBUG RUNTIME
		 */
		super.postLoad();
		...
		if (search(false).size() == 0) {
			warn("postLoad", "DEBT/ObjectServiceSimplicite 401 on valid token (not yet expired) on "+getName()+" test search size="+String.valueOf(this.search(false).size())+" force login", this);
			try {
				getAPIClient().login(true);
			} catch (Exception e) {
				error("postLoad", "EXCEPTION CAUGHT/getAPIClient().login()", e, this);
			}
		}
		/**/
	}

1 Like

Normalement le relogin est géré automatiquement par les objets service.

On parle de quelle version/révision ? Je pose la question car en 5.1.27 on a corrigé un pb qui laissait actif en mémoire un grant associé à un token expiré. Il y a peut être un effet de bord de cette correction avec les tokens externes…

Merci pour ton retour rapide.
Je confirme, reproduit (et contourné) ce matin sur la dernière 5.1.27 mais je traînais ce truc depuis plusieurs mois donc ce n’est a priori pas lié à la 5.1.27.

OK je vais refaire des tests entre 2 instances en 5.1.27.

  1. On est bie d’accord qu’on parle ici de tokens interne Simplicité ?
  2. On est en mode JWT ou dummy tokens (cf. le paramètre systeme USERTOKENS_MODE) ?

Oui, token Simplicité

Non, actuellement on est en token “simple”.

Je vais tester en mode “jwt”.

Et quel valeur pour USE_USERTOKENS ?
Et pour USERTOKENS_DURATION ?
Il faudrait vérifier ces param systèmes des deux cotés, mais surtout du coté qui est appelé

Est-on bien en 5.1.27 des deux cotés ?

Et quid de la date système et du timezone des 2 cotés ? Je pose la question car des tokens courts et des dates système décalées peuvent rendre les tokens invalide dès leur création.

yes / 24h des deux côtés

  • L’appelant est sur notre infra Intranet (timezone Europe/Paris par défaut, surchargé avec Europe/Paris via le paramètre TOMCAT_TIMEZONE)
  • L’appelé est sur l’infra AWS (timezone ~ … Irlande … j’ai pas le code sous la main ~ par défaut, surchargé avec Europe/Paris via le paramètre TOMCAT_TIMEZONE passé à tomcat)

Yes pour tout ?

La valeur des 3 params système cités et les versions exactes ont potentiellement de l’importance => je veux être sûr de tester dans les même conditions que toi

Pour l’heure vue de Simplicité (coté serveur et coté base de données) il faut aller dans les health checks et vérifier que SystemDate et DBDate sont tous bien cohérents (des deux cotés)

Je précise que je viens de mettre “jwt” comme valeur remplacée et que le problème remonté a été produit en mode “simple”.

Ta copie d’écran est bien du coté qui est appelé ?

Quid des ces paramètres de l’autre coté ?

Quid des versions des 2 cotés ?

Quid des dates système et database des 2 cotés ?

Désolé d’être pénible mais j’ai absolument besoin de ces infos pour monter un environnement de test conforme à ton cas d’usage.

Oui, copie d’écran faite sur l’appelé mais c’est le même paramétrage des deux côtés.

NB: Je reproduis le problème (en trichant) en forçant un logout du user sur l’appelé (par un cURL en ligne de commande) puis en rafraichissant la liste de l’objet service-simplicite sur l’appelant.

Si je fais les health check simultanément, je suis aligné à la seconde près…

Côté appelé :

[Platform]
Status=OK
Version=5.1.25
BuiltOn=2022-01-19 23:27
Git=release/d262833d2618a163394f3c302730ea45bfa30fa3
Encoding=UTF-8
EndpointIP=172.17.0.7
EndpointURL=http://89f363885271:8080
TimeZone=Europe/Paris
SystemDate=2022-02-02 15:51:42

[Application]
ApplicationVersion=1.0.0
ContextPath=
ContextURL=https://int.rfi.dev.aws.renault.com
ActiveSessions=1
TotalUsers=28
EnabledUsers=25
LastLoginDate=2022-02-02 15:48:46

[Server]
ServerInfo=Apache Tomcat/9.0.56
ServerType=WEB
ServerActiveSessions=16

[OS]
Name=Linux
Architecture=amd64
Version=4.14.256-197.484.amzn2.x86_64
DockerImageName=centos7
SystemEncoding=UTF-8

[Disk]
DiskFree=21467
DiskUsable=21467
DiskTotal=30707

[JavaVM]
Version=17.0.1
Vendor=Eclipse Adoptium
VMName=OpenJDK 64-Bit Server VM
VMVersion=17.0.1+12
ScriptEngine=rhino
ScriptEngineVersion=Rhino 1.7.13 2020 09 02
HeapFree=107980
HeapSize=506944
HeapMaxSize=1773888
TotalFreeSize=1374924

[Cache]
GrantCache=0
GrantCacheMax=0
GrantCacheRatio=0
ObjectCache=227
ObjectCacheMax=10000
ObjectCacheRatio=2
ProcessCache=10
ProcessCacheMax=10000
ProcessCacheRatio=0

[Database]
Vendor=3
ProductName=PostgreSQL
ProductVersion=10.17
DriverName=PostgreSQL JDBC Driver
DriverVersion=42.3.1
DBDate=2022-02-02 15:51:42
DBDateOffset=0
DBPatchLevel=5;P01;8eec3aaa281ce44b39212dcadbfe22cf
UsingBLOBs=true

[Healthcheck]
Date=2022-02-02 15:51:42
ElapsedTime=15

Côté appelant :

[Platform]
Status=OK
Version=5.1.27
BuiltOn=2022-01-30 19:16
Git=release/b227ee3270e90962ec6ec8002f60513da75b1301
Encoding=UTF-8
EndpointIP=21.0.9.2
EndpointURL=http://95c477d801a9:8080
TimeZone=Europe/Paris
SystemDate=2022-02-02 15:49:17

[Application]
ApplicationVersion=1.0.0
ContextPath=
ContextURL=https://bca.dok-dev.intra.renault.fr
ActiveSessions=1
TotalUsers=5398
EnabledUsers=74
LastLoginDate=2022-02-02 15:33:46

[Server]
ServerInfo=Apache Tomcat/9.0.58
ServerType=WEB
ServerActiveSessions=5

[OS]
Name=Linux
Architecture=amd64
Version=3.10.0-1160.49.1.el7.x86_64
DockerImageName=centos7
SystemEncoding=UTF-8

[Disk]
DiskFree=495080
DiskUsable=495080
DiskTotal=510726

[JavaVM]
Version=17.0.2
Vendor=Eclipse Adoptium
VMName=OpenJDK 64-Bit Server VM
VMVersion=17.0.2+8
ScriptEngine=rhino
ScriptEngineVersion=Rhino 1.7.13 2020 09 02
HeapFree=286655
HeapSize=1013632
HeapMaxSize=1013632
TotalFreeSize=286655

[Cache]
GrantCache=0
GrantCacheMax=0
GrantCacheRatio=0
ObjectCache=656
ObjectCacheMax=10000
ObjectCacheRatio=6
ProcessCache=1
ProcessCacheMax=10000
ProcessCacheRatio=0

[Database]
Vendor=2
ProductName=MySQL
ProductVersion=5.6.39-log
DriverName=MySQL Connector/J
DriverVersion=mysql-connector-java-8.0.28 (Revision: 7ff2161da3899f379fb3171b6538b191b1c5c7e2)
DBDate=2022-02-02 15:49:17
DBDateOffset=0
DBPatchLevel=5;P01;8eec3aaa281ce44b39212dcadbfe22cf
UsingBLOBs=true

[Healthcheck]
Date=2022-02-02 15:49:17
ElapsedTime=15

Ok il manque toujours la vérification de l’alignement des 4 dates via les 2 health checks… à nouveau désolé d’insister mais j’ai besoin d’éliminer des pistes car il y a une grosse combinatoire de cas.

En fait, j’ai l’impression que le problème n’est pas dans la non-reconnexion sur token expiré (test basé sur les dates d’expiration) mais la non-reconnexion sur 401 (réaction sur informations d’authentification invalides).

  • Avec ma verrue dans le postLoad qui force un login(true), ça repart dès que l’objet service-simplicité est réinstancié par l’appelant.
  • Sans la verrue, l’appelant ne se reconnecte pas (au moins tant que le token n’est pas expiré)

Ok ça fera partie des tests que je vais faire mais ça ne me dit toujours pas si les 4 dates sont bien alignées…

J’ai collé le détail des health… a priori les dates sont bien alignées (à la seconde près).

Ah oui désolé je n’avais pas vu passer la réponse.
Je teste tout ça et je te dis.

Au passage, search(false).size() c’est ça ramène la totalité des records… quitte à faire ce genre de chose fais un count() ce sera infiniment moins couteux

C’est corrigé, merci :slight_smile:

En relisant le code il pourrait potentiellement y avoir un écart entrer la valeur de la date d’expiration du token retournée au client vs celle gérée coté serveur.

Le fait de désormais mieux gérer l’éviction du grant associé à un token expiré coté serveur a certainement mis en lumière ce cas.

Je vais essayer de cerner dans quelles configurations exactes client/serveur on peut se retrouver dans ce cas.

Il faut effectivement que le code du call gère le retry sur exception car le check sur les dates est trop lié à la config des serveurs, et se fait toujours “avant” le call, et pas “pendant”.

C’est ce qui est fait pas exemple dans KeyCloakTool.call.
KeyCloak répond comme ceci :

400 bad request = expired refresh token => là il faut recréer une nouvelle session
401 unauthorized = expired token => demande de nouveau token si possible sinon nouvelle session

Il faudrait reproduire le même fonctionnement, de renouveler le token ou la session sur exception + retry.

En 5.2+ ca a été pas mal refactoré. On peut sans doute facilement ajouter une requête de “ping” avant toute vraie requête pour gérer la reconnexion et/ou checker l’expiration du token. Je regarde ça.

1 Like