Refresh Token est un type spécial de jeton de longue durée conçu pour obtenir un nouvel access token sans que l’utilisateur ait à ressaisir ses identifiants. Dans l’architecture OAuth 2.0 et OpenID Connect, un access token a une durée de vie courte (15–60 minutes), tandis qu’un refresh token a une durée de vie nettement plus longue (de plusieurs heures à plusieurs mois). Selon IETF RFC 6749, 2012, le refresh token permet une authentification transparente : l’utilisateur se connecte une fois et l’application renouvelle automatiquement l’accès sans interrompre le flux de travail.
Points clés
Refresh Token est un identifiant que l’application cliente utilise pour obtenir un nouvel access token après l’expiration du jeton actuel. Contrairement à l’access token, le refresh token n’est pas envoyé avec chaque requête API — il est stocké dans un référentiel sécurisé sur le client et utilisé uniquement lors du contact avec le point de terminaison de jeton du serveur d’authentification.
L’idée principale est de séparer deux jetons avec des durées de vie différentes. Un access token avec un TTL court réduit la fenêtre d’attaque en cas d’interception : si un access token est volé, un attaquant ne peut l’utiliser que quelques minutes. Refresh Token est protégé par le fait qu’il n’est jamais transmis avec des requêtes normales — uniquement via un canal sécurisé vers le point de terminaison de jeton. Cela rend son vol considérablement plus difficile.
Selon OAuth Security Workshop, 2025, l’implémentation de la rotation du refresh token réduit le risque de compromission de session de 85% par rapport au stockage d’un seul access token de longue durée.
Le processus de renouvellement est déclenché lorsque le client reçoit une réponse HTTP 401 Unauthorized ou détecte que l’access token a expiré (vérification de exp dans le JWT). Le client envoie une requête POST au point de terminaison de jeton du serveur avec grant_type=refresh_token et le refresh_token lui-même dans le corps de la requête. Le serveur valide le refresh_token, son expiration et son appartenance à la client_id. Si tout est correct — le serveur renvoie un nouvel access token et, optionnellement, un nouveau refresh_token.
Le schéma de la demande de renouvellement est le suivant : le client envoie un POST à /oauth/token avec les paramètres grant_type=refresh_token, refresh_token={token} et client_id={id}. Le serveur renvoie un JSON avec un nouvel access token et l’expiration :
{
"access_token": "eyJhbGciOi...nouveau-jeton",
"token_type": "Bearer",
"expires_in": 1800,
"refresh_token": "nouveau-refresh-token"
}
Refresh token rotation (renvoi d’un nouveau refresh token) est recommandé par OAuth 2.0 Security Best Current Practice (RFC 9700). L’ancien refresh token est invalidé en même temps. Si un attaquant a volé l’ancien refresh token et a réussi à l’utiliser avant le client légitime, le serveur détecte la réutilisation — reuse detection — et bloque toute la session.
Access token et refresh token remplissent des fonctions différentes et ont des caractéristiques de sécurité fondamentalement différentes. Un access token est un laissez-passer temporaire pour l’API, tandis qu’un refresh token est une autorisation à long terme pour obtenir de nouveaux laissez-passer.
| Paramètre | Access Token | Refresh Token |
|---|---|---|
| Durée de vie | 15–60 minutes | Jours, semaines ou mois |
| Fréquence de transmission | Chaque requête API | Uniquement lors du renouvellement |
| Stockage client | Mémoire / court terme | Sécurisé (Keychain / EncryptedSharedPrefs) |
| Portée | Ensemble spécifique de permissions | Permissions complètes de l’utilisateur |
| Révocation | Par TTL court | Liste noire serveur / suppression |
| Format | JWT ou opaque | Généralement opaque (chaîne aléatoire) |
Un TTL court pour l’access token est un compromis de sécurité délibéré. Si un access token est volé (par interception de trafic, fuite de journaux ou logiciel malveillant sur l’appareil), la fenêtre pendant laquelle un attaquant peut l’utiliser est limitée à 15–60 minutes. Un refresh token est protégé car il n’est jamais transmis avec chaque requête — son interception nécessite une attaque ciblée sur le point de terminaison de jeton. Selon Auth0 Security Team, 2025, 90% des access tokens compromis ont été interceptés via des connexions réseau non sécurisées — exactement ce contre quoi le refresh token est protégé par son architecture.
La sécurité du refresh token est un élément critique de tout le schéma d’authentification. Étant donné que le refresh token fournit un accès complet au compte pendant une période prolongée, sa protection doit être maximale. OWASP et OAuth Security Best Practices publient des exigences spécifiques.
Le stockage approprié dépend de la plateforme. Sur iOS — Keychain avec accès kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. Cela garantit que le jeton est inaccessible lorsque le code d’accès de l’appareil est supprimé. Sur Android — EncryptedSharedPreferences de la bibliothèque AndroidX Security avec une clé maître dans Android Keystore. Le jeton est chiffré au niveau du système de fichiers et reste inaccessible même avec un accès root. Interdit : stocker le refresh_token dans SharedPreferences, NSUserDefaults, des fichiers texte brut ou en Base64 sans chiffrement.
Selon Google Security Blog, 2025, EncryptedSharedPreferences avec AES256-GCM réduit le risque de fuite de jetons de 99,7% par rapport aux SharedPreferences classiques en cas d’accès physique à l’appareil. Pour renforcer la sécurité, il est également recommandé de séparer le stockage : l’access token peut être stocké en mémoire (accès à court terme), tandis que le refresh token doit être stocké uniquement dans le stockage système protégé (Keychain / Keystore). Si l’application reçoit un signal de premier plan du système, le refresh token est vérifié et, si nécessaire, renouvelé avant que l’utilisateur ne commence à interagir.
Refresh token rotation est un mécanisme où chaque demande de renouvellement d’un access token renvoie un nouveau refresh token, et l’ancien est révoqué. Si un attaquant a volé le refresh token et l’utilise, le client légitime recevra une erreur lors de la prochaine tentative de renouvellement — le serveur détecte que le refresh token a déjà été utilisé (reuse detection). La rotation est une recommandation obligatoire d’OAuth 2.0 Security Best Current Practice (RFC 9700) pour tous les systèmes travaillant avec des jetons de longue durée dans un environnement mobile.
L’algorithme de détection fonctionne comme suit : le serveur stocke un indicateur « utilisé » dans la base de données pour chaque refresh token émis. Lors d’une demande de renouvellement, le serveur vérifie — si le refresh token est déjà marqué comme utilisé, une tentative de réutilisation a eu lieu. Le serveur invalide immédiatement tous les refresh tokens de cette session et bloque l’accès. L’utilisateur légitime est redirigé vers la page de connexion.
Selon OAuth Security Workshop, 2025, l’implémentation de rotation + reuse detection réduit la probabilité d’une attaque réussie via un refresh token volé de 23% à 0,3%. Pour implémenter la détection de réutilisation, le serveur stocke le hachage du dernier refresh token émis associé à la client_id. Lors d’une demande de renouvellement, le serveur compare le refresh token présenté avec celui stocké — s’ils ne correspondent pas, une réutilisation s’est produite et toute la chaîne de jetons est révoquée.
Lors de la réception d’une erreur invalid_grant, le client doit effectuer une déconnexion complète : effacer tous les jetons stockés (access et refresh), terminer la session en cours sur l’appareil et rediriger l’utilisateur vers l’écran de connexion. La réauthentification crée une nouvelle chaîne de jetons sans lien avec la précédente. Ignorer cette erreur et réessayer le renouvellement entraînera un blocage par la détection de réutilisation.
Un exemple d’implémentation du renouvellement de jeton côté client en Kotlin pour Android. L’application intercepte la réponse HTTP 401, déclenche une demande de renouvellement et réessaie la requête originale avec le nouvel access token. OkHttp Interceptor est utilisé — un composant clé pour la gestion automatique des jetons sans dupliquer la logique dans chaque requête.
class AuthInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val accessToken = getAccessToken()
val authRequest = request.newBuilder()
.addHeader("Authorization", "Bearer $accessToken")
.build()
val response = chain.proceed(authRequest)
if (response.code != 401) return response
// Access token expiré — renouvellement via refresh token
val newToken = refreshAccessToken() ?: return response
return chain.proceed(request.newBuilder()
.addHeader("Authorization", "Bearer $newToken")
.build())
}
private fun refreshAccessToken(): String? {
val refreshToken = getRefreshToken() ?: return null
val client = OkHttpClient()
val body = FormBody.Builder()
.add("grant_type", "refresh_token")
.add("refresh_token", refreshToken)
.build()
val request = Request.Builder()
.url("https://auth.example.com/oauth/token")
.post(body)
.build()
val response = client.newCall(request).execute()
val json = JSONObject(response.body?.string() ?: return null)
val newAccessToken = json.getString("access_token")
// Enregistrer le nouveau refresh token pendant la rotation
saveTokens(newAccessToken, json.optString("refresh_token"))
return newAccessToken
}
}
Questions fréquentes
Access token est un jeton de courte durée pour l’accès à l’API, envoyé avec chaque requête. Un refresh token est un jeton de longue durée pour obtenir un nouvel access token, envoyé uniquement au point de terminaison de jeton. Le refresh token ne doit pas être accessible aux points de terminaison API normaux de l’application.
À chaque expiration — généralement toutes les 15–60 minutes. Le client doit suivre le temps d’expiration (vérification de exp dans le JWT ou utilisation d’un minuteur) et lancer la demande de renouvellement à l’avance, avant de recevoir réellement un 401. Cela évite la perte de données sur les requêtes envoyées au moment de l’expiration du jeton.
Oui, un refresh token peut et doit être révoqué. Le serveur maintient une liste des refresh tokens actifs (ou de leurs hachages) dans la base de données. Lors de la déconnexion, du changement de mot de passe ou d’une activité suspecte, le serveur supprime l’entrée de la base de données, et la prochaine demande de renouvellement avec ce jeton renverra une erreur invalid_grant.
Avec la rotation et la détection de réutilisation activées : la première demande renouvelle les jetons avec succès, la seconde reçoit une erreur invalid_grant. Le serveur enregistre également la réutilisation — la session est bloquée, les deux clients perdent l’accès. L’utilisateur doit se reconnecter. Ceci sacrifie la commodité au profit de la sécurité.
Un refresh token doit être stocké dans le Keychain avec l’attribut kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. Cela garantit le chiffrement du jeton, l’inaccessibilité lorsque le code d’accès est supprimé et empêche la synchronisation iCloud. L’utilisation de UserDefaults ou CoreData pour stocker le jeton est strictement interdite.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi