- Renombrar 02-integraciones/ → 03-integraciones/ (resolver prefijo duplicado) - Renombrar 02-devops/ → 04-devops/ (resolver prefijo duplicado) - Renombrar architecture/ → 97-adr/ (agregar prefijo numerico) - Actualizar _MAP.md con nueva estructura y version 2.1.0 Estructura final: - 00-vision-general/ - 01-modulos/ - 02-especificaciones/ - 03-integraciones/ - 04-devops/ - 97-adr/ Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
190 lines
4.4 KiB
Markdown
190 lines
4.4 KiB
Markdown
---
|
|
id: "ADR-002"
|
|
title: "Autenticacion con JWT y OAuth 2.0"
|
|
type: "ADR"
|
|
status: "Accepted"
|
|
priority: "P0"
|
|
supersedes: "N/A"
|
|
superseded_by: "N/A"
|
|
version: "1.0.0"
|
|
created_date: "2026-01-07"
|
|
updated_date: "2026-01-10"
|
|
---
|
|
|
|
# ADR-002: Autenticación con JWT y OAuth 2.0
|
|
|
|
## Metadata
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| ID | ADR-002 |
|
|
| Estado | Accepted |
|
|
| Fecha | 2026-01-10 |
|
|
| Supersede | N/A |
|
|
|
|
## Contexto
|
|
|
|
Template SaaS necesita un sistema de autenticación robusto que soporte:
|
|
- Login tradicional con email/password
|
|
- Autenticación social (OAuth)
|
|
- Multi-Factor Authentication (MFA)
|
|
- Sesiones persistentes y seguras
|
|
- API stateless para escalabilidad
|
|
|
|
## Opciones Consideradas
|
|
|
|
### Opción 1: Session-based Authentication
|
|
**Descripción:** Sesiones almacenadas en servidor, cookie con session ID.
|
|
|
|
**Pros:**
|
|
- Simple de implementar
|
|
- Revocación inmediata
|
|
- Menor payload en requests
|
|
|
|
**Contras:**
|
|
- Requiere almacenamiento de sesiones
|
|
- No escalable horizontalmente sin sticky sessions
|
|
- Problemas con múltiples dominios/apps
|
|
|
|
### Opción 2: JWT con Refresh Tokens ✓
|
|
**Descripción:** Access tokens cortos + refresh tokens largos.
|
|
|
|
**Pros:**
|
|
- Stateless (escalable horizontalmente)
|
|
- Información en token (claims)
|
|
- Funciona con múltiples servicios
|
|
- Ideal para SPAs y mobile
|
|
|
|
**Contras:**
|
|
- Revocación requiere blacklist
|
|
- Tokens más grandes
|
|
- Complejidad de refresh flow
|
|
|
|
### Opción 3: OAuth-only (delegado)
|
|
**Descripción:** Usar solo proveedores externos (Google, etc).
|
|
|
|
**Pros:**
|
|
- Sin manejo de passwords
|
|
- Seguridad delegada
|
|
- UX familiar
|
|
|
|
**Contras:**
|
|
- Dependencia de terceros
|
|
- No todos los usuarios tienen cuentas sociales
|
|
- Pérdida de control
|
|
|
|
## Decisión
|
|
|
|
**Elegimos JWT con Refresh Tokens + OAuth opcional** porque:
|
|
|
|
1. **Flexibilidad:** Soporta login local y social
|
|
2. **Escalabilidad:** Stateless permite escalar horizontalmente
|
|
3. **Seguridad:** Access tokens cortos + refresh tokens rotativos
|
|
4. **UX:** Sesiones persistentes sin re-login frecuente
|
|
|
|
## Implementación
|
|
|
|
### Estructura de Tokens
|
|
|
|
```typescript
|
|
// Access Token (15 min)
|
|
{
|
|
sub: 'user-uuid',
|
|
tenant_id: 'tenant-uuid',
|
|
email: 'user@example.com',
|
|
roles: ['admin', 'member'],
|
|
iat: 1234567890,
|
|
exp: 1234568790
|
|
}
|
|
|
|
// Refresh Token (7 días)
|
|
{
|
|
sub: 'user-uuid',
|
|
tenant_id: 'tenant-uuid',
|
|
type: 'refresh',
|
|
jti: 'unique-token-id', // para revocación
|
|
iat: 1234567890,
|
|
exp: 1235172690
|
|
}
|
|
```
|
|
|
|
### Token Storage
|
|
|
|
| Token | Almacenamiento | Duración |
|
|
|-------|---------------|----------|
|
|
| Access Token | Memory/localStorage | 15 min |
|
|
| Refresh Token | httpOnly cookie | 7 días |
|
|
|
|
### OAuth Flow
|
|
|
|
```
|
|
1. Usuario click "Login con Google"
|
|
2. Redirect a Google OAuth
|
|
3. Google callback con code
|
|
4. Backend intercambia code por tokens Google
|
|
5. Backend crea/vincula usuario local
|
|
6. Backend genera JWT propios
|
|
7. Redirect a app con tokens
|
|
```
|
|
|
|
### MFA (TOTP)
|
|
|
|
```typescript
|
|
// Activación
|
|
1. Generar secreto TOTP
|
|
2. Mostrar QR code
|
|
3. Verificar código inicial
|
|
4. Guardar secreto encriptado
|
|
|
|
// Login con MFA
|
|
1. Validar email/password
|
|
2. Si MFA activo, solicitar código
|
|
3. Validar código TOTP
|
|
4. Emitir tokens
|
|
```
|
|
|
|
### Endpoints
|
|
|
|
| Método | Endpoint | Descripción |
|
|
|--------|----------|-------------|
|
|
| POST | `/auth/register` | Registro nuevo usuario |
|
|
| POST | `/auth/login` | Login email/password |
|
|
| POST | `/auth/refresh` | Renovar access token |
|
|
| POST | `/auth/logout` | Revocar refresh token |
|
|
| GET | `/auth/oauth/:provider` | Iniciar OAuth |
|
|
| GET | `/auth/oauth/:provider/callback` | Callback OAuth |
|
|
| POST | `/auth/mfa/enable` | Activar MFA |
|
|
| POST | `/auth/mfa/verify` | Verificar código MFA |
|
|
|
|
## Consecuencias
|
|
|
|
### Positivas
|
|
- Sistema flexible y escalable
|
|
- Soporte para múltiples métodos de auth
|
|
- Tokens con información útil (claims)
|
|
- Refresh tokens permiten sesiones largas
|
|
- Compatible con microservicios
|
|
|
|
### Negativas
|
|
- Complejidad adicional vs sessions
|
|
- Requiere manejo cuidadoso de refresh
|
|
- Blacklist necesaria para revocación inmediata
|
|
|
|
### Seguridad Implementada
|
|
- Passwords hasheados con bcrypt (cost 12)
|
|
- Refresh tokens rotativos (one-time use)
|
|
- Rate limiting en endpoints de auth
|
|
- CORS restrictivo
|
|
- HTTPS obligatorio
|
|
|
|
## Referencias
|
|
|
|
- [JWT Best Practices (RFC 8725)](https://tools.ietf.org/html/rfc8725)
|
|
- [OAuth 2.0 (RFC 6749)](https://tools.ietf.org/html/rfc6749)
|
|
- [TOTP (RFC 6238)](https://tools.ietf.org/html/rfc6238)
|
|
- Implementación: `apps/backend/src/modules/auth/`
|
|
|
|
---
|
|
|
|
**Fecha decision:** 2026-01-10
|
|
**Autores:** Claude Code (Arquitectura)
|