Jetons d’actualisation et expiration
Implémentez un renouvellement sécurisé des jetons.
Jetons d’actualisation et expiration est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 4 leçons au total.
Le problème de l’expiration
Les jetons d’accès de courte durée sont sécurisés, mais peu pratiques : obliger les utilisateurs à se connecter toutes les 15 minutes nuit à l’expérience utilisateur.
La solution est un jeton d’actualisation : un identifiant distinct à plus longue durée de vie, utilisé pour obtenir de nouveaux jetons d’accès sans saisir à nouveau de mot de passe.
// access token: 15 minutes
// refresh token: 7-30 daysQu’est-ce qu’un jeton d’actualisation
Un jeton d’actualisation est généralement une chaîne aléatoire opaque (et non un JWT). Comme sa durée de vie est longue, il doit être stocké côté serveur afin de pouvoir être révoqué.
Générez-le avec un RNG sécurisé sur le plan cryptographique.
public static string GenerateRefreshToken()
{
var bytes = new byte[64];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(bytes);
return Convert.ToBase64String(bytes);
}Stockage des jetons d’actualisation
Conservez chaque jeton d’actualisation avec son propriétaire, sa date d’expiration et un indicateur de révocation. Vous pourrez ainsi l’invalider en cas de déconnexion ou de vol.
public class RefreshToken
{
public int Id { get; set; }
public string Token { get; set; } = default!;
public int UserId { get; set; }
public DateTime ExpiresAt { get; set; }
public bool IsRevoked { get; set; }
}Émission des deux jetons lors de la connexion
Lors d’une connexion réussie, renvoyez le jeton d’accès à courte durée de vie et un nouveau jeton d’actualisation. Enregistrez le jeton d’actualisation dans la base de données.
var access = tokenService.CreateAccessToken(user);
var refresh = new RefreshToken
{
Token = TokenService.GenerateRefreshToken(),
UserId = user.Id,
ExpiresAt = DateTime.UtcNow.AddDays(7)
};
db.RefreshTokens.Add(refresh);
await db.SaveChangesAsync();
return Results.Ok(new { access, refresh = refresh.Token });Le point de terminaison d’actualisation
Un point de terminaison /refresh dédié accepte un jeton d’actualisation et, s’il est valide, émet un tout nouveau jeton d’accès.
app.MapPost("/refresh", async (RefreshDto dto, AppDb db, TokenService tokens) =>
{
var stored = await db.RefreshTokens
.SingleOrDefaultAsync(r => r.Token == dto.RefreshToken);
if (stored is null || stored.IsRevoked ||
stored.ExpiresAt < DateTime.UtcNow)
return Results.Unauthorized();
var user = await db.Users.FindAsync(stored.UserId);
var access = tokens.CreateAccessToken(user!);
return Results.Ok(new { access });
});Rotation des jetons d’actualisation
La rotation renforce le flux : chaque fois qu’un jeton d’actualisation est utilisé, révoquez-le et émettez-en un nouveau. Un jeton volé qui a déjà été utilisé devient alors inutilisable.
stored.IsRevoked = true; // burn the old one
var next = new RefreshToken
{
Token = TokenService.GenerateRefreshToken(),
UserId = stored.UserId,
ExpiresAt = DateTime.UtcNow.AddDays(7)
};
db.RefreshTokens.Add(next);
await db.SaveChangesAsync();Détection de la réutilisation des jetons
Avec la rotation, vous pouvez détecter un vol : si un jeton déjà révoqué est présenté de nouveau, considérez cela comme une compromission et révoquez toute la famille de jetons de l’utilisateur.
if (stored.IsRevoked)
{
// This token was already used - likely stolen.
await RevokeAllUserTokens(stored.UserId, db);
return Results.Unauthorized();
}Déconnexion et révocation
La déconnexion révoque simplement le jeton d’actualisation actuel. Le jeton d’accès expirera de lui-même dans les minutes qui suivent.
app.MapPost("/logout", async (RefreshDto dto, AppDb db) =>
{
var stored = await db.RefreshTokens
.SingleOrDefaultAsync(r => r.Token == dto.RefreshToken);
if (stored is not null) stored.IsRevoked = true;
await db.SaveChangesAsync();
return Results.Ok();
}).RequireAuthorization();Où stocker les jetons côté client
Dans les navigateurs, la solution la plus sûre consiste à stocker le jeton d’actualisation dans un cookie HttpOnly et sécurisé afin que JavaScript ne puisse pas le lire, ce qui limite le vol par XSS.
Le jeton d’accès de courte durée peut être conservé en mémoire.
Response.Cookies.Append("refresh", refresh.Token, new CookieOptions
{
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.Strict,
Expires = refresh.ExpiresAt
});Nettoyage des jetons expirés
Les jetons d’actualisation s’accumulent. Exécutez régulièrement une tâche en arrière-plan (par exemple, un service hébergé) pour supprimer les lignes expirées ou révoquées.
await db.RefreshTokens
.Where(r => r.ExpiresAt < DateTime.UtcNow || r.IsRevoked)
.ExecuteDeleteAsync();Choix des durées de vie
Trouvez le juste équilibre entre sécurité et commodité :
- Jeton d’accès : 5 à 15 minutes, afin de limiter l’exposition d’un jeton divulgué.
- Jeton d’actualisation : de quelques heures à plusieurs semaines, selon la sensibilité.
- Utilisez la rotation pour toute durée supérieure à une journée.
AccessTokenLifetime = TimeSpan.FromMinutes(15);
RefreshTokenLifetime = TimeSpan.FromDays(7);Vérification rapide
Vérifiez votre compréhension du flux d’actualisation.
Récapitulatif
Vous avez implémenté le flux des jetons d’actualisation :
- Émettez un jeton d’accès de courte durée ainsi qu’un jeton d’actualisation long, opaque et stocké côté serveur.
- Un point de terminaison
/refreshéchange un jeton d’actualisation valide contre un nouveau jeton d’accès. - La rotation et la détection de réutilisation renforcent la protection contre le vol.
- Stockez les jetons d’actualisation dans des cookies HttpOnly et supprimez les lignes expirées.
Le cours sur l’authentification JWT est maintenant terminé.
Questions Fréquemment Posées
La leçon « Jetons d’actualisation et expiration » est-elle gratuite ?
Oui — le texte complet de « Jetons d’actualisation et expiration » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Jetons d’actualisation et expiration » ?
Implémentez un renouvellement sécurisé des jetons. Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer C# Academy ?
Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Jetons d’actualisation et expiration » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?
Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Structure et revendications JWT
- Configurer l’authentification JWT Bearer
- Émettre des jetons
- Jetons d’actualisation et expiration