Aller au contenu principal
Sécurité

Refresh Token

6 min de lecture
  • sécurité
  • authentification
  • api
Refresh Token : renouveler sans réauthentifier

Vous vous connectez à une application. Quinze minutes plus tard, vous êtes déconnecté. "Session expirée, veuillez vous reconnecter." Frustrant. Mais si le token d'accès durait des semaines, un attaquant qui le vole aurait accès à votre compte pendant des semaines. Le Refresh Token résout ce dilemme : garder l'utilisateur connecté sans compromettre la sécurité.

Le problème : durée de vie vs sécurité

Un système d'authentification par token fonctionne en deux temps : l'utilisateur s'authentifie (login + mot de passe), et le serveur lui donne un token qu'il présente à chaque requête. Le serveur vérifie le token au lieu de redemander le mot de passe.

Mais quelle durée de vie donner à ce token ?

  • Trop court (5 minutes) → l'utilisateur doit se reconnecter constamment. Expérience horrible.
  • Trop long (30 jours) → si le token est volé (XSS, interception réseau, fuite de logs), l'attaquant a un accès prolongé.

La solution : deux tokens avec des rôles différents.

Access Token vs Refresh Token

Access TokenRefresh Token
RôleAccéder aux ressources protégéesObtenir un nouvel Access Token
Durée de vieCourte (5-15 minutes)Longue (7-30 jours)
StockageMémoire ou localStorageCookie httpOnly sécurisé
Envoyé àChaque requête APIUniquement au endpoint de refresh
Si voléImpact limité (expire vite)Peut être révoqué côté serveur

L'Access Token est le badge d'accès quotidien. Court, léger, utilisé partout. S'il est compromis, les dégâts sont limités par sa courte durée de vie.

Le Refresh Token est la carte d'identité stockée dans un coffre. On ne la sort que pour renouveler le badge. Il est stocké de manière sécurisée et n'est jamais envoyé aux API métier.

Le cycle de vie complet

1. LOGIN
   Utilisateur → [email + mot de passe] → Serveur Auth
   Serveur Auth → [Access Token + Refresh Token] → Utilisateur

2. APPELS API (pendant 15 minutes)
   Utilisateur → [Access Token dans le header] → API
   API → vérifie le token → renvoie les données

3. ACCESS TOKEN EXPIRÉ
   Utilisateur → [Access Token expiré] → API
   API → 401 Unauthorized

4. REFRESH
   Utilisateur → [Refresh Token] → Serveur Auth
   Serveur Auth → vérifie le Refresh Token
   Serveur Auth → [Nouvel Access Token + Nouveau Refresh Token] → Utilisateur

5. REPRISE NORMALE
   Utilisateur → [Nouvel Access Token] → API
   API → 200 OK

Tout ce processus est transparent pour l'utilisateur. Il ne voit jamais l'écran de connexion tant que son Refresh Token est valide.

Implémentation côté client

async function fetchWithAuth(url: string, options: RequestInit = {}) {
  let accessToken = getAccessToken();
 
  let response = await fetch(url, {
    ...options,
    headers: { ...options.headers, Authorization: `Bearer ${accessToken}` }
  });
 
  // Si le token est expiré, on le renouvelle
  if (response.status === 401) {
    const refreshResponse = await fetch("/auth/refresh", {
      method: "POST",
      credentials: "include" // Envoie le cookie httpOnly
    });
 
    if (!refreshResponse.ok) {
      // Le Refresh Token est aussi expiré → redirection login
      redirectToLogin();
      return;
    }
 
    const { accessToken: newToken } = await refreshResponse.json();
    setAccessToken(newToken);
 
    // On rejoue la requête originale avec le nouveau token
    response = await fetch(url, {
      ...options,
      headers: { ...options.headers, Authorization: `Bearer ${newToken}` }
    });
  }
 
  return response;
}

Où stocker les tokens

C'est la question qui génère le plus de débats. Voici les recommandations actuelles :

Access Token → en mémoire (variable JavaScript). Pas dans le localStorage, pas dans un cookie accessible en JS. En mémoire, le token disparaît quand l'onglet se ferme et n'est pas accessible via une attaque XSS.

Refresh Token → dans un cookie httpOnly, Secure, SameSite=Strict. Ce cookie n'est pas lisible par JavaScript (protection XSS). Il n'est envoyé que vers votre domaine (protection CSRF). Il n'est transmis qu'en HTTPS.

Set-Cookie: refresh_token=abc123;
  HttpOnly;
  Secure;
  SameSite=Strict;
  Path=/auth/refresh;
  Max-Age=2592000

Le Path=/auth/refresh est important : le cookie n'est envoyé qu'au endpoint de renouvellement, pas à toutes les requêtes API.

La rotation de tokens

Une bonne pratique de sécurité : à chaque utilisation du Refresh Token, le serveur en émet un nouveau et invalide l'ancien. C'est la rotation de tokens.

Pourquoi ? Si un attaquant vole un Refresh Token et l'utilise, le serveur émet un nouveau token pour l'attaquant. Quand l'utilisateur légitime essaie d'utiliser l'ancien token (désormais invalide), le serveur détecte l'anomalie et peut révoquer toute la famille de tokens, forçant une reconnexion.

Utilisation normale :
  RT-1 → [refresh] → RT-2 (RT-1 invalidé)
  RT-2 → [refresh] → RT-3 (RT-2 invalidé)

Attaque détectée :
  Attaquant utilise RT-1 (volé) → RT-2' émis
  Utilisateur utilise RT-2 → REFUSÉ (RT-2 déjà remplacé)
  → Serveur révoque toute la chaîne → Reconnexion forcée

Les erreurs courantes

Stocker le Refresh Token dans le localStorage. C'est la faille la plus répandue. Le localStorage est accessible par n'importe quel script JavaScript sur la page. Une attaque XSS suffit pour voler le token.

Ne pas implémenter la rotation. Sans rotation, un Refresh Token volé reste valide pendant toute sa durée de vie. Avec rotation, la fenêtre d'exploitation est réduite à une seule utilisation.

Ne pas prévoir la révocation. Les Refresh Tokens doivent pouvoir être révoqués côté serveur — lors d'un changement de mot de passe, d'une déconnexion explicite, ou d'une détection d'anomalie. Cela implique de les stocker en base de données.

Mettre une durée de vie trop longue sur l'Access Token. Si votre Access Token dure 24 heures, vous n'avez plus besoin de Refresh Token — et vous avez un problème de sécurité. La valeur typique est 5 à 15 minutes.


Le Refresh Token est le mécanisme qui permet de concilier sécurité et expérience utilisateur. Des Access Tokens courts pour limiter l'exposition, un Refresh Token long et sécurisé pour éviter la reconnexion. Avec la rotation et le stockage en cookie httpOnly, vous avez un système d'authentification robuste contre la majorité des attaques courantes.