Nous développons l'application Spring avec frontend React/Redux. Nous l'avons intégré avec succès au service d'authentification Keycloak. Cependant, nous avons rencontré un comportement indésirable après l'expiration du jeton d'accès. Notre restMiddleware ressemble à ceci (simplifié):Couvre-clé | Ne peut pas attendre sur updateToken() dans la fonction async
function restMiddleware() {
return (next) => async (action) => {
try{
await keycloak.updateToken(5);
res = await fetch(restCall.url, {
...restCall.options, ...{
credentials: 'same-origin',
headers: {
Authorization: 'Bearer ' + keycloak.token
}
}
});
}catch(e){}
}
Le problème est que, après expiration du jeton et updateToken() est exécutée, la fonction async ne s'arrête pas et invoque fetch() immédiatement, avant nouveau jeton d'accès est reçu. Cela empêche bien sûr la requête d'extraction de réussir et provoque une réponse avec le code 401. updateToken() renvoie une promesse, donc je ne vois aucune raison pour laquelle l'attente ne fonctionnerait pas dessus, ce qui est certainement le cas. J'ai confirmé que la fonction dans updateToken().success(*function*)
s'exécutera après un rafraîchissement de jeton réussi et que le placement de fetch() à l'intérieur résoudrait le problème, mais à cause de notre construction de middleware, je ne peux pas le faire. J'ai développé cette solution de contournement:
function refreshToken(minValidity) {
return new Promise((resolve, reject) => {
keycloak.updateToken(minValidity).success(function() {
resolve()
}).error(function() {
reject()
});
});
}
function restMiddleware() {
return (next) => async (action) => {
try{
await refreshToken(5);
res = await fetch(restCall.url, {
...restCall.options, ...{
credentials: 'same-origin',
headers: {
Authorization: 'Bearer ' + keycloak.token
}
}
});
}catch(e){}
}
Et il fonctionne, mais il est pas élégant.
La question est: pourquoi la première solution n'a pas fonctionné? Pourquoi je ne peux pas attendre sur updateToken() et utiliser updateToken(). Success() à la place?
Je suppose que cela pourrait être un bug et de confirmer que c'est le but principal de cette question.
Je viens de regarder dans les keycloak.js, où cette méthode est définie et je peux voir le point. Ce que renvoie updateToken() n'est pas du tout une promesse (à partir de la spécification ECMAScript). C'est un objet personnalisé ne contenant que des fonctions success() et error() que les créateurs de Keycloak ont nommé ... "promettre l'objet" -.- "La méthode updateToken retourne un objet promesse qui permet d'invoquer facilement le service uniquement si le jeton a été actualisé avec succès et par exemple afficher une erreur à l'utilisateur si ce n'était pas. " Il est très déroutant, à mon avis, ils ne devraient pas utiliser cette description. – BJanusz