0Pricing
C# Academy · Lección

Tokens de actualización y caducidad

Implemente una renovación segura de tokens.

Tokens de actualización y caducidad es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 4 lecciones en total.

El problema de la caducidad

Los access tokens de corta duración son seguros, pero poco prácticos: obligar a los usuarios a iniciar sesión cada 15 minutos ofrece una mala experiencia de usuario.

La solución es un refresh token: una credencial independiente y de mayor duración que se utiliza para obtener nuevos access tokens sin volver a introducir la contraseña.

// access token: 15 minutes
// refresh token: 7-30 days

Qué es un refresh token

Normalmente, un refresh token es una cadena aleatoria opaca (no un JWT). Como tiene una larga duración, debe almacenarse en el servidor para poder revocarlo.

Genérelo mediante un generador de números aleatorios criptográficamente seguro.

public static string GenerateRefreshToken()
{
    var bytes = new byte[64];
    using var rng = RandomNumberGenerator.Create();
    rng.GetBytes(bytes);
    return Convert.ToBase64String(bytes);
}

Almacenamiento de refresh tokens

Conserve cada refresh token junto con su propietario, su fecha de caducidad y un indicador de revocación. Esto permite invalidarlo al cerrar sesión o si ha sido robado.

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; }
}

Emisión de ambos tokens al iniciar sesión

Cuando el inicio de sesión se realiza correctamente, devuelva el access token de corta duración y un refresh token nuevo. Guarde el refresh token en la base de datos.

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 });

El endpoint de renovación

Un endpoint específico /refresh acepta un refresh token y, si es válido, emite un access token completamente nuevo.

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 });
});

Rotación de refresh tokens

La rotación refuerza el flujo: cada vez que se utiliza un refresh token, se revoca y se emite uno nuevo. De este modo, un token robado que ya se haya utilizado deja de ser válido.

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();

Detección de reutilización de tokens

Con la rotación puede detectar robos: si se vuelve a presentar un token que ya estaba revocado, considérelo una intrusión y revoque toda la familia de tokens del usuario.

if (stored.IsRevoked)
{
    // This token was already used - likely stolen.
    await RevokeAllUserTokens(stored.UserId, db);
    return Results.Unauthorized();
}

Cierre de sesión y revocación

El cierre de sesión simplemente revoca el refresh token actual. El access token caducará por sí solo en cuestión de minutos.

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();

Dónde almacenar los tokens en el cliente

En los navegadores, el patrón más seguro almacena el refresh token en una cookie HttpOnly y Secure para que JavaScript no pueda leerlo, lo que reduce el riesgo de robo mediante XSS.

El access token de corta duración puede conservarse en memoria.

Response.Cookies.Append("refresh", refresh.Token, new CookieOptions
{
    HttpOnly = true,
    Secure = true,
    SameSite = SameSiteMode.Strict,
    Expires = refresh.ExpiresAt
});

Limpieza de tokens caducados

Los refresh tokens se acumulan. Ejecute periódicamente un trabajo en segundo plano (por ejemplo, un servicio hospedado) para eliminar las filas caducadas o revocadas.

await db.RefreshTokens
    .Where(r => r.ExpiresAt < DateTime.UtcNow || r.IsRevoked)
    .ExecuteDeleteAsync();

Elección de las duraciones

Equilibre la seguridad y la comodidad:

  • Access token: 5-15 minutos; limita la exposición de un token filtrado.
  • Refresh token: de horas a semanas, según la sensibilidad.
  • Utilice la rotación para cualquier duración superior a un día.
AccessTokenLifetime  = TimeSpan.FromMinutes(15);
RefreshTokenLifetime = TimeSpan.FromDays(7);

Comprobación rápida

Compruebe cuánto entiende del flujo de renovación.

Resumen

Ha implementado el flujo de refresh tokens:

  • Emita un access token de corta duración junto con un refresh token largo, opaco y almacenado en el servidor.
  • Un endpoint /refresh intercambia un refresh token válido por un access token nuevo.
  • La rotación y la detección de reutilización refuerzan la protección frente al robo.
  • Almacene los refresh tokens en cookies HttpOnly y limpie las filas caducadas.

Con esto finaliza el curso de autenticación con JWT.

Preguntas frecuentes

¿La lección «Tokens de actualización y caducidad» es gratis?

Sí — el texto completo de «Tokens de actualización y caducidad» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Tokens de actualización y caducidad»?

Implemente una renovación segura de tokens. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C# Academy?

No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Tokens de actualización y caducidad»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C# Academy?

Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Estructura y claims de JWT
  2. Configuración de la autenticación JWT Bearer
  3. Emisión de tokens
  4. Tokens de actualización y caducidad
← Volver a C# Academy