erp-core/docs/03-requerimientos/RF-auth/RF-AUTH-003.md

10 KiB

RF-AUTH-003: Refresh Token y Renovacion de Sesion

Identificacion

Campo Valor
ID RF-AUTH-003
Modulo MGN-001
Nombre Modulo Auth - Autenticacion
Prioridad P0
Complejidad Media
Estado Aprobado
Autor System
Fecha 2025-12-05

Descripcion

El sistema debe permitir renovar el access token utilizando un refresh token valido, sin requerir que el usuario vuelva a ingresar sus credenciales. Esto permite mantener sesiones de larga duracion de forma segura, mientras los access tokens tienen vida corta.

Contexto de Negocio

Los access tokens tienen vida corta (15 minutos) por seguridad. Sin un mecanismo de refresh, los usuarios tendrian que re-autenticarse constantemente, lo cual afecta negativamente la experiencia de usuario. El refresh token permite mantener la sesion activa hasta 7 dias sin comprometer la seguridad.


Criterios de Aceptacion

  • CA-001: El sistema debe aceptar un refresh token valido y generar nuevos tokens
  • CA-002: El nuevo access token debe tener los mismos claims que el original
  • CA-003: El refresh token usado debe invalidarse (rotacion de tokens)
  • CA-004: Se debe generar un nuevo refresh token con cada renovacion
  • CA-005: El sistema debe rechazar refresh tokens expirados con error 401
  • CA-006: El sistema debe rechazar refresh tokens revocados con error 401
  • CA-007: El sistema debe detectar y prevenir reuso de refresh tokens (token replay)
  • CA-008: El frontend debe renovar automaticamente antes de que expire el access token

Ejemplos de Verificacion

Scenario: Renovacion exitosa de tokens
  Given un usuario con refresh token valido
  When el usuario envia el refresh token a /api/v1/auth/refresh
  Then el sistema invalida el refresh token anterior
  And genera un nuevo par de tokens (access + refresh)
  And responde con status 200 y los nuevos tokens

Scenario: Refresh token expirado
  Given un usuario con refresh token expirado
  When el usuario intenta renovar tokens
  Then el sistema responde con status 401
  And el mensaje es "Refresh token expirado"
  And el usuario debe hacer login nuevamente

Scenario: Deteccion de token replay (reuso)
  Given un refresh token que ya fue usado para renovar
  When alguien intenta usar ese mismo refresh token
  Then el sistema detecta el reuso
  And invalida TODOS los tokens del usuario (seguridad)
  And responde con status 401
  And el mensaje es "Sesion comprometida, por favor inicie sesion"

Reglas de Negocio

ID Regla Validacion
RN-001 Refresh token valido por 7 dias JWT exp claim
RN-002 Cada refresh genera nuevo refresh token (rotacion) Token replacement
RN-003 Refresh token usado se invalida inmediatamente Marcar como usado en BD
RN-004 Reuso de refresh token invalida toda la familia Revocar todos tokens del usuario
RN-005 Maximo 5 sesiones activas por usuario Contador de sesiones
RN-006 El refresh se hace 1 minuto antes de expiracion Frontend timer

Token Family (Familia de Tokens)

Cada refresh token pertenece a una "familia" que se origina en un login. Si se detecta reuso de un token de esa familia, toda la familia se invalida.

Login -> RT1 -> RT2 -> RT3 (familia activa)
                  ↳ RT2 reusado? -> Invalida RT1, RT2, RT3

Impacto en Capas

Database

Elemento Accion Descripcion
Tabla modificar refresh_tokens - agregar campos
Columna agregar family_id UUID - familia del token
Columna agregar is_used BOOLEAN - si ya fue usado
Columna agregar used_at TIMESTAMPTZ - cuando se uso
Columna agregar replaced_by UUID - token que lo reemplazo
Indice crear idx_refresh_tokens_family

Backend

Elemento Accion Descripcion
Controller crear AuthController.refresh()
Method crear TokenService.refreshTokens()
Method crear TokenService.detectTokenReuse()
Method crear TokenService.revokeTokenFamily()
DTO crear RefreshTokenDto
DTO crear TokenResponseDto
Endpoint crear POST /api/v1/auth/refresh

Frontend

Elemento Accion Descripcion
Service modificar tokenService.refreshTokens()
Interceptor crear Auto-refresh interceptor
Timer crear Refresh timer (1 min antes de exp)
Handler crear Token expiration handler

Dependencias

Depende de (Bloqueantes)

ID Requerimiento Estado
RF-AUTH-001 Login Genera tokens iniciales
RF-AUTH-002 JWT Tokens Estructura de tokens

Dependencias Relacionadas

ID Requerimiento Relacion
RF-AUTH-004 Logout Revoca refresh tokens

Especificaciones Tecnicas

Flujo de Refresh

┌─────────────────────────────────────────────────────────────────┐
│ 1. Frontend detecta que access token expira pronto              │
│    (1 minuto antes de exp)                                      │
└───────────────────────────┬─────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────────┐
│ 2. Frontend envia refresh token a POST /api/v1/auth/refresh     │
└───────────────────────────┬─────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────────┐
│ 3. Backend valida refresh token                                  │
│    - Verifica firma                                              │
│    - Verifica expiracion                                         │
│    - Verifica que no este usado (is_used = false)               │
│    - Verifica que no este revocado                              │
└───────────────────────────┬─────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────────┐
│ 4. Si es valido:                                                 │
│    - Marca token actual como usado (is_used = true)             │
│    - Genera nuevo access token                                   │
│    - Genera nuevo refresh token (misma family_id)               │
│    - Actualiza replaced_by del token anterior                   │
│    - Retorna nuevos tokens                                       │
└───────────────────────────┬─────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────────┐
│ 5. Frontend almacena nuevos tokens                               │
│    - Actualiza access token en memoria/storage                  │
│    - Actualiza refresh token en httpOnly cookie                 │
│    - Reinicia timer de refresh                                   │
└─────────────────────────────────────────────────────────────────┘

Deteccion de Token Replay

async refreshTokens(refreshToken: string): Promise<TokenPair> {
  const decoded = this.decodeToken(refreshToken);
  const storedToken = await this.refreshTokenRepo.findOne({
    where: { jti: decoded.jti }
  });

  // Detectar reuso
  if (storedToken.isUsed) {
    // ALERTA: Token replay detectado
    await this.revokeTokenFamily(storedToken.familyId);
    throw new UnauthorizedException('Sesion comprometida');
  }

  // Marcar como usado
  storedToken.isUsed = true;
  storedToken.usedAt = new Date();

  // Generar nuevos tokens
  const newTokens = await this.generateTokenPair(decoded.sub, decoded.tid);

  // Vincular tokens
  storedToken.replacedBy = newTokens.refreshTokenId;
  await this.refreshTokenRepo.save(storedToken);

  return newTokens;
}

Datos de Prueba

Escenario Entrada Resultado
Refresh exitoso Refresh token valido 200, nuevos tokens
Token expirado RT con exp < now 401, "Token expirado"
Token ya usado RT con is_used = true 401, "Sesion comprometida"
Token revocado RT en revoked_tokens 401, "Token revocado"
Sin refresh token Body vacio 400, "Refresh token requerido"

Estimacion

Capa Story Points Notas
Database 2 Columnas adicionales en refresh_tokens
Backend 5 Logica de rotacion y deteccion reuso
Frontend 3 Auto-refresh interceptor y timer
Total 10

Notas Adicionales

  • El refresh token debe enviarse en httpOnly cookie, no en body (previene XSS)
  • Considerar sliding window: extender expiracion si hay actividad
  • Implementar rate limiting en endpoint de refresh (max 1 req/segundo)
  • Loguear todos los refreshes para auditoria
  • En caso de breach, proporcionar endpoint para revocar todas las sesiones

Historial de Cambios

Version Fecha Autor Cambios
1.0 2025-12-05 System Creacion inicial

Aprobaciones

Rol Nombre Fecha Firma
Analista System 2025-12-05 [x]
Tech Lead - - [ ]
Product Owner - - [ ]