.NET
Ce que j'ai appris en implémentant la JWT authentication en .NET
L'expiration de l'access token est la partie facile à gérer. Le refresh token qui expire silencieusement, sans chemin de failure explicite, c'est ce qui a vraiment causé des déconnexions déroutantes jusqu'à ce que je lui en donne un.
Les access tokens qui expirent, c'est la partie facile à gérer. Mon client attrape un 401, appelle l'endpoint de refresh, obtient un nouvel access token, et continue. La partie qui me pose vraiment problème, c'est le refresh token lui-même qui expire, silencieusement, sans rien qui dise au client que c'est arrivé jusqu'à ce qu'il essaie de l'utiliser et échoue.
Où ça casse vraiment
L'access token a une durée de vie courte exprès, donc j'ai construit le flux de refresh autour de ça dès le début. Ce que je n'avais pas prévu au début, c'est que le refresh token a aussi sa propre expiration, plus longue. Quand celle-ci arrive à son terme, l'appel de refresh lui-même échoue, et si je ne gère que l'échec de l'access token, ce second échec n'a nulle part où aller. L'utilisateur se retrouve juste déconnecté sans raison claire, en plein milieu de ce qu'il était en train de faire.
Ce que je change
L'endpoint de refresh a besoin de son propre chemin de failure explicite, séparé d'un 401 normal sur un request ordinaire. Si le refresh token est expiré ou invalide, ça doit être routé vers quelque chose de spécifique, retour à un écran de connexion avec un vrai message, pas juste une erreur d'auth générique qui a l'air identique à n'importe quel autre request raté.
public async Task<IActionResult> Refresh(RefreshRequest request)
{
var storedToken = await _tokenStore.FindAsync(request.RefreshToken);
if (storedToken is null || storedToken.ExpiresAt < DateTimeOffset.UtcNow)
{
return Unauthorized(new { reason = "refresh_token_expired" });
}
var newAccessToken = _tokenService.CreateAccessToken(storedToken.UserId);
return Ok(new { accessToken = newAccessToken });
}
Ce champ reason est la pièce qui me manquait. Sans lui, le client n'a aucun moyen de distinguer « votre access token a expiré, essayez de rafraîchir » de « votre refresh token est mort, reconnectez-vous ». Sinon, les deux reviennent comme le même échec générique.
Ce qui en est vraiment resté
L'expiration de token, ce sont en fait deux événements séparés sur deux timers différents, et un seul d'entre eux a un chemin de récupération évident intégré au flux normal. L'autre doit être géré exprès, sinon il apparaît juste comme une déconnexion silencieuse et déroutante sans cause claire.