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

7.4 KiB

RF-AUTH-002: Generacion y Validacion de JWT Tokens

Identificacion

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

Descripcion

El sistema debe implementar un mecanismo de tokens JWT (JSON Web Tokens) para autenticar y autorizar las peticiones de los usuarios. Los tokens deben contener la informacion necesaria para identificar al usuario y su tenant, permitiendo el acceso a los recursos del sistema de forma segura y stateless.

Contexto de Negocio

Los tokens JWT permiten autenticacion stateless, lo cual es esencial para:

  • Escalabilidad horizontal del backend
  • APIs REST verdaderamente stateless
  • Soporte para multiples clientes (web, mobile, integraciones)
  • Aislamiento multi-tenant mediante tenant_id en el payload

Criterios de Aceptacion

  • CA-001: El sistema debe generar access tokens con expiracion de 15 minutos
  • CA-002: El sistema debe generar refresh tokens con expiracion de 7 dias
  • CA-003: El payload del token debe incluir: userId, tenantId, email, roles
  • CA-004: Los tokens deben firmarse con algoritmo RS256 (asymmetric keys)
  • CA-005: El sistema debe validar la firma del token en cada request
  • CA-006: El sistema debe rechazar tokens expirados con error 401
  • CA-007: El sistema debe rechazar tokens con firma invalida con error 401
  • CA-008: El sistema debe extraer el usuario del token y adjuntarlo al request

Ejemplos de Verificacion

Scenario: Validacion de token valido
  Given un usuario autenticado con un access token valido
  When el usuario hace una peticion a un endpoint protegido
  Then el sistema valida la firma del token
  And extrae el userId y tenantId del payload
  And permite el acceso al recurso

Scenario: Token expirado
  Given un usuario con un access token expirado
  When el usuario hace una peticion a un endpoint protegido
  Then el sistema responde con status 401
  And el mensaje es "Token expirado"
  And el header incluye WWW-Authenticate: Bearer error="token_expired"

Scenario: Token con firma invalida
  Given un token modificado o con firma incorrecta
  When se intenta acceder a un endpoint protegido
  Then el sistema responde con status 401
  And el mensaje es "Token invalido"

Reglas de Negocio

ID Regla Validacion
RN-001 Access token expira en 15 minutos JWT exp claim
RN-002 Refresh token expira en 7 dias JWT exp claim
RN-003 Los tokens usan algoritmo RS256 Asymmetric signing
RN-004 El payload incluye jti (JWT ID) unico UUID v4
RN-005 El issuer (iss) debe ser "erp-core" JWT iss claim
RN-006 El audience (aud) debe ser "erp-api" JWT aud claim
RN-007 El tenant_id es obligatorio (excepto superadmin) Validacion en middleware

Estructura del JWT Payload

{
  "sub": "user-uuid",           // Subject: User ID
  "tid": "tenant-uuid",         // Tenant ID
  "email": "user@example.com",  // Email del usuario
  "roles": ["admin", "user"],   // Roles del usuario
  "permissions": ["read", "write"], // Permisos directos
  "iat": 1701792000,            // Issued At
  "exp": 1701792900,            // Expiration (15 min)
  "iss": "erp-core",            // Issuer
  "aud": "erp-api",             // Audience
  "jti": "unique-token-id"      // JWT ID
}

Impacto en Capas

Database

Elemento Accion Descripcion
Tabla crear refresh_tokens - almacenar refresh tokens
Tabla crear revoked_tokens - tokens revocados
Columna - refresh_tokens.token_hash (hash del token)
Columna - refresh_tokens.expires_at
Columna - refresh_tokens.device_info
Indice crear idx_refresh_tokens_user
Indice crear idx_revoked_tokens_jti

Backend

Elemento Accion Descripcion
Service crear TokenService
Method crear generateAccessToken()
Method crear generateRefreshToken()
Method crear validateToken()
Method crear decodeToken()
Guard crear JwtAuthGuard
Middleware crear TokenMiddleware
Config crear JWT keys (public/private)
Interface crear JwtPayload
Interface crear TokenPair

Frontend

Elemento Accion Descripcion
Service crear tokenService
Method - getAccessToken()
Method - setTokens()
Method - clearTokens()
Method - isTokenExpired()
Interceptor crear Axios interceptor para adjuntar token
Storage usar localStorage/sessionStorage para tokens

Dependencias

Depende de (Bloqueantes)

ID Requerimiento Estado
RF-AUTH-001 Login Genera los tokens

Dependencias Relacionadas

ID Requerimiento Relacion
RF-AUTH-003 Refresh Token Usa refresh token
RF-AUTH-004 Logout Revoca tokens

Especificaciones Tecnicas

Generacion de Claves RS256

# Generar clave privada
openssl genrsa -out private.key 2048

# Extraer clave publica
openssl rsa -in private.key -pubout -out public.key

Configuracion de Tokens

// config/jwt.config.ts
export const jwtConfig = {
  accessToken: {
    algorithm: 'RS256',
    expiresIn: '15m',
    issuer: 'erp-core',
    audience: 'erp-api',
  },
  refreshToken: {
    algorithm: 'RS256',
    expiresIn: '7d',
    issuer: 'erp-core',
    audience: 'erp-api',
  },
};

Ejemplo de Token Generado

Header:
{
  "alg": "RS256",
  "typ": "JWT"
}

Payload:
{
  "sub": "550e8400-e29b-41d4-a716-446655440000",
  "tid": "tenant-123",
  "email": "user@example.com",
  "roles": ["admin"],
  "iat": 1701792000,
  "exp": 1701792900,
  "iss": "erp-core",
  "aud": "erp-api",
  "jti": "abc123"
}

Datos de Prueba

Escenario Token Resultado
Token valido JWT firmado correctamente 200, acceso permitido
Token expirado exp < now 401, "Token expirado"
Firma invalida Token modificado 401, "Token invalido"
Sin token Header Authorization vacio 401, "Token requerido"
Formato incorrecto "Bearer abc123" (no JWT) 401, "Token malformado"

Estimacion

Capa Story Points Notas
Database 2 Tablas refresh_tokens, revoked_tokens
Backend 5 TokenService, Guards, Middleware
Frontend 2 Token storage e interceptors
Total 9

Notas Adicionales

  • Las claves privadas deben almacenarse en variables de entorno o secrets manager
  • Considerar rotacion de claves cada 90 dias
  • Implementar JWK (JSON Web Key) endpoint para distribuir clave publica
  • El refresh token NO debe almacenarse en localStorage (usar httpOnly cookie)
  • Implementar token blacklist en Redis para logout inmediato

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 - - [ ]