## Documentation - Align MCH-029 to MCH-032 with template-saas modules (SAAS-008 to SAAS-015) - Create MCH-034 (Analytics) and MCH-035 (Reports) from SAAS-016/017 - Update PLAN-DESARROLLO.md with Phase 7 and 8 - Update _MAP.md indexes (35 total epics) ## Database (5 new schemas, 14 tables) - Add storage schema: buckets, files, signed_urls - Add webhooks schema: endpoints, deliveries - Add audit schema: logs, retention_policies - Add features schema: flags, tenant_flags (14 seeds) - Add analytics schema: metrics, events, reports, report_schedules - Add auth.oauth_connections for MCH-030 - Add timestamptz_to_date() IMMUTABLE function - Update EXPECTED_SCHEMAS in recreate-database.sh ## Analysis Reports - ANALISIS-INTEGRACION-TEMPLATE-SAAS-2026-01-13.md - VALIDACION-COHERENCIA-2026-01-13.md - GAP-ANALYSIS-BD-2026-01-13.md - REPORTE-EJECUCION-2026-01-13.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
337 lines
14 KiB
Markdown
337 lines
14 KiB
Markdown
---
|
|
id: EPIC-MCH-030
|
|
type: Epic
|
|
title: "MCH-030: Auth Social (OAuth 2.0)"
|
|
code: MCH-030
|
|
status: Planificado
|
|
phase: 7
|
|
priority: P1
|
|
created_at: 2026-01-10
|
|
updated_at: 2026-01-10
|
|
simco_version: "4.0.1"
|
|
dependencies:
|
|
blocks: []
|
|
depends_on: ["MCH-029"]
|
|
---
|
|
|
|
# MCH-030: Auth Social (OAuth 2.0)
|
|
|
|
## Metadata
|
|
- **Codigo:** MCH-030
|
|
- **Fase:** 7 - Expansion
|
|
- **Prioridad:** P1
|
|
- **Estado:** Planificado
|
|
- **Story Points:** 8
|
|
- **Sprint Objetivo:** Sprint 8
|
|
|
|
## Descripcion
|
|
|
|
Agregar autenticacion social via OAuth 2.0 con Google y Apple Sign-In para simplificar el onboarding de usuarios. Permite registro e inicio de sesion con un clic, reduciendo friccion y aumentando conversion.
|
|
|
|
## Objetivos
|
|
|
|
1. Implementar Login con Google
|
|
2. Implementar Sign in with Apple (requerido para iOS)
|
|
3. Permitir vinculacion de cuentas sociales a cuenta existente
|
|
4. Obtener perfil basico del usuario (nombre, email, foto)
|
|
|
|
## Alcance
|
|
|
|
### Incluido
|
|
- OAuth 2.0 con Google
|
|
- Sign in with Apple (web + iOS)
|
|
- Vinculacion de multiples proveedores a una cuenta
|
|
- Sync de foto de perfil
|
|
|
|
### Excluido
|
|
- Facebook Login (baja prioridad)
|
|
- Microsoft/LinkedIn (B2B futuro)
|
|
- Two-factor authentication (MCH-002 existente)
|
|
|
|
## Arquitectura
|
|
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ MCH-030: Auth Social │
|
|
└─────────────────────────────────────┘
|
|
│
|
|
┌─────────────────┴─────────────────┐
|
|
▼ ▼
|
|
┌──────────┐ ┌──────────┐
|
|
│ Google │ │ Apple │
|
|
│ OAuth │ │ Sign-In │
|
|
└────┬─────┘ └────┬─────┘
|
|
│ │
|
|
▼ ▼
|
|
┌─────────────────────────────────────────┐
|
|
│ Passport.js Strategies │
|
|
└─────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────┐
|
|
│ oauth_accounts (tabla) │
|
|
│ user_id | provider | provider_id │
|
|
└─────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────┐
|
|
│ auth.users (existente) │
|
|
└─────────────────────────────────────────┘
|
|
```
|
|
|
|
## Entregables
|
|
|
|
| Entregable | Estado | Sprint | Ubicacion |
|
|
|------------|--------|--------|-----------|
|
|
| Google OAuth Strategy | Planificado | 8 | `apps/backend/src/modules/auth/strategies/` |
|
|
| Apple OAuth Strategy | Planificado | 8 | `apps/backend/src/modules/auth/strategies/` |
|
|
| Tabla oauth_accounts | Planificado | 8 | `database/schemas/16-oauth.sql` |
|
|
| Endpoints /auth/google, /auth/apple | Planificado | 8 | `apps/backend/src/modules/auth/` |
|
|
| UI botones sociales web | Planificado | 8 | `apps/web/src/pages/auth/` |
|
|
| Implementacion mobile | Planificado | 8 | `apps/mobile/src/screens/auth/` |
|
|
|
|
## Dependencias
|
|
|
|
### Depende de
|
|
- MCH-029 (Email para verificacion de cuenta vinculada)
|
|
|
|
### Bloquea a
|
|
- Ninguna
|
|
|
|
---
|
|
|
|
## Historias de Usuario
|
|
|
|
### MCH-US-105: Login con Google
|
|
|
|
**Como** usuario nuevo
|
|
**Quiero** registrarme/iniciar sesion con mi cuenta de Google
|
|
**Para** no tener que recordar otra contrasena
|
|
|
|
**Story Points:** 5
|
|
|
|
**Criterios de Aceptacion:**
|
|
- [CA-105-1] Boton "Continuar con Google" visible en login y registro
|
|
- [CA-105-2] Registro automatico si no existe cuenta con ese email
|
|
- [CA-105-3] Vinculacion automatica si ya existe cuenta con mismo email
|
|
- [CA-105-4] Obtiene nombre y foto de perfil de Google
|
|
- [CA-105-5] Funciona en web (popup) y mobile (Expo AuthSession)
|
|
|
|
**Tareas:**
|
|
| ID | Tarea | Tipo | SP |
|
|
|----|-------|------|-----|
|
|
| MCH-TT-105-01 | DDL tabla oauth_accounts | DDL | 0.5 |
|
|
| MCH-TT-105-02 | Google OAuth strategy (Passport) | Backend | 1 |
|
|
| MCH-TT-105-03 | Endpoint /auth/google | Backend | 0.5 |
|
|
| MCH-TT-105-04 | Callback handler /auth/google/callback | Backend | 0.5 |
|
|
| MCH-TT-105-05 | Servicio de vinculacion de cuentas | Backend | 0.5 |
|
|
| MCH-TT-105-06 | UI boton Google en web | Frontend | 0.5 |
|
|
| MCH-TT-105-07 | Implementacion mobile (Expo) | Frontend | 1 |
|
|
| MCH-TT-105-08 | Tests unitarios e integracion | Test | 0.5 |
|
|
| MCH-TT-105-09 | Documentacion en INT-012 | Docs | 0 |
|
|
|
|
---
|
|
|
|
### MCH-US-106: Login con Apple
|
|
|
|
**Como** usuario de iOS
|
|
**Quiero** iniciar sesion con Apple ID
|
|
**Para** usar autenticacion nativa de mi dispositivo
|
|
|
|
**Story Points:** 3
|
|
|
|
**Criterios de Aceptacion:**
|
|
- [CA-106-1] Sign in with Apple funcional en iOS nativo
|
|
- [CA-106-2] Fallback web para Android y Desktop
|
|
- [CA-106-3] Manejo correcto de email oculto (relay de Apple)
|
|
- [CA-106-4] Registro automatico con nombre del usuario
|
|
- [CA-106-5] Cumple requisitos App Store Review Guidelines
|
|
|
|
**Tareas:**
|
|
| ID | Tarea | Tipo | SP |
|
|
|----|-------|------|-----|
|
|
| MCH-TT-106-01 | Apple OAuth strategy | Backend | 0.5 |
|
|
| MCH-TT-106-02 | Endpoint /auth/apple | Backend | 0.5 |
|
|
| MCH-TT-106-03 | Manejo de private email relay | Backend | 0.5 |
|
|
| MCH-TT-106-04 | Implementacion iOS nativa | Frontend | 0.5 |
|
|
| MCH-TT-106-05 | Fallback web con apple-signin-api | Frontend | 0.5 |
|
|
| MCH-TT-106-06 | Tests | Test | 0.25 |
|
|
| MCH-TT-106-07 | Documentacion en INT-012 | Docs | 0.25 |
|
|
|
|
---
|
|
|
|
## Resumen de Story Points
|
|
|
|
| Historia | SP | Sprint |
|
|
|----------|-----|--------|
|
|
| MCH-US-105: Login con Google | 5 | 8 |
|
|
| MCH-US-106: Login con Apple | 3 | 8 |
|
|
| **TOTAL** | **8** | 8 |
|
|
|
|
---
|
|
|
|
## Criterios de Aceptacion de Epica
|
|
|
|
- [ ] Login con Google funcional en web y mobile
|
|
- [ ] Sign in with Apple funcional en iOS
|
|
- [ ] Cuentas vinculadas correctamente
|
|
- [ ] No se crean duplicados de usuarios
|
|
- [ ] Cobertura de tests >80%
|
|
|
|
## Notas Tecnicas
|
|
|
|
### Configuracion Google Cloud Console
|
|
1. Crear proyecto en Google Cloud Console
|
|
2. Habilitar Google+ API
|
|
3. Crear OAuth 2.0 Client ID (Web Application)
|
|
4. Configurar redirect URIs:
|
|
- `https://api.michangarrito.com/auth/google/callback`
|
|
- `http://localhost:3000/auth/google/callback` (dev)
|
|
|
|
### Configuracion Apple Developer
|
|
1. App ID con Sign in with Apple capability
|
|
2. Service ID para web
|
|
3. Key privada para validar tokens
|
|
4. Configurar domains y redirect URLs
|
|
|
|
### Variables de Entorno
|
|
```env
|
|
# Google OAuth
|
|
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
|
|
GOOGLE_CLIENT_SECRET=xxx
|
|
|
|
# Apple Sign-In
|
|
APPLE_CLIENT_ID=com.michangarrito.app
|
|
APPLE_TEAM_ID=XXXXXXXXXX
|
|
APPLE_KEY_ID=XXXXXXXXXX
|
|
APPLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----..."
|
|
```
|
|
|
|
## Integraciones Relacionadas
|
|
|
|
- [INT-012: OAuth Social](../02-integraciones/INT-012-oauth-social.md)
|
|
|
|
## ADRs Relacionados
|
|
|
|
- [ADR-0010: OAuth Social Strategy](../97-adr/ADR-0010-oauth-social.md)
|
|
|
|
---
|
|
|
|
## Especificaciones Tecnicas Detalladas (Ref: SAAS-015)
|
|
|
|
### Proveedores Soportados
|
|
|
|
| Proveedor | Enum Value | Scopes | URL Autorizacion |
|
|
|-----------|------------|--------|------------------|
|
|
| Google | `google` | openid email profile | accounts.google.com/o/oauth2/v2/auth |
|
|
| Apple | `apple` | name email | appleid.apple.com/auth/authorize |
|
|
|
|
### Modelo de Datos
|
|
|
|
#### Tabla: auth.oauth_connections
|
|
|
|
| Columna | Tipo | Nullable | Descripcion |
|
|
|---------|------|----------|-------------|
|
|
| id | uuid | NO | PK, generado automaticamente |
|
|
| tenant_id | uuid | NO | FK a tenants.tenants(id) |
|
|
| user_id | uuid | NO | FK a users.users(id) |
|
|
| provider | auth.oauth_provider | NO | Enum: google, apple |
|
|
| provider_user_id | varchar(255) | NO | ID unico del usuario en el proveedor |
|
|
| provider_email | varchar(255) | SI | Email del usuario en el proveedor |
|
|
| provider_name | varchar(255) | SI | Nombre del usuario en el proveedor |
|
|
| provider_avatar_url | varchar(500) | SI | URL del avatar del proveedor |
|
|
| access_token | text | SI | Token de acceso OAuth (encriptado) |
|
|
| refresh_token | text | SI | Token de refresco OAuth (encriptado) |
|
|
| token_expires_at | timestamptz | SI | Expiracion del access token |
|
|
| created_at | timestamptz | NO | Fecha de creacion |
|
|
| updated_at | timestamptz | NO | Fecha de actualizacion |
|
|
| last_used_at | timestamptz | SI | Ultimo uso de esta conexion |
|
|
|
|
### Endpoints API
|
|
|
|
| Metodo | Endpoint | Descripcion | Auth |
|
|
|--------|----------|-------------|------|
|
|
| GET | /auth/oauth/:provider/url | Obtener URL de autorizacion | Publica |
|
|
| POST | /auth/oauth/:provider/callback | Callback OAuth (login/registro) | Publica |
|
|
| GET | /auth/oauth/connections | Listar conexiones del usuario | JWT |
|
|
| POST | /auth/oauth/connections/:provider/link | Vincular nuevo proveedor | JWT |
|
|
| DELETE | /auth/oauth/connections/:provider | Desvincular proveedor | JWT |
|
|
|
|
### Flujo de Autenticacion OAuth
|
|
|
|
```
|
|
Usuario Frontend Backend Proveedor
|
|
│ │ │ │
|
|
│ Click "Login Google" │ │ │
|
|
│───────────────────────>│ │ │
|
|
│ │ GET /auth/oauth/google/url │
|
|
│ │────────────────────────>│ │
|
|
│ │ │ │
|
|
│ │ { url, state } │ │
|
|
│ │<────────────────────────│ │
|
|
│ │ │ │
|
|
│ │ Redirect to Google │ │
|
|
│<───────────────────────│ │ │
|
|
│ │ │ │
|
|
│ Autoriza en Google │ │ │
|
|
│──────────────────────────────────────────────────────────────────────────>│
|
|
│ │ │ │
|
|
│ Redirect con code │ │ │
|
|
│<──────────────────────────────────────────────────────────────────────────│
|
|
│ │ │ │
|
|
│ code + state │ │ │
|
|
│───────────────────────>│ │ │
|
|
│ │ POST /auth/oauth/google/callback │
|
|
│ │ { profile, tokens } │ │
|
|
│ │────────────────────────>│ Busca/Crea usuario │
|
|
│ │ │ Crea conexion OAuth │
|
|
│ │ │ Genera JWT │
|
|
│ │ { user, accessToken } │ │
|
|
│ │<────────────────────────│ │
|
|
│ Usuario autenticado │ │ │
|
|
│<───────────────────────│ │ │
|
|
```
|
|
|
|
### Seguridad
|
|
|
|
1. **State Parameter**: El state incluye tenant_id, timestamp y random string en base64 para prevenir CSRF
|
|
2. **Tokens Encriptados**: Los tokens OAuth se almacenan encriptados en base de datos
|
|
3. **RLS Multi-tenant**: Aislamiento completo por tenant usando Row-Level Security
|
|
4. **Proteccion de Desvinculacion**: No se permite desvincular el unico metodo de autenticacion
|
|
5. **Email Pre-verificado**: Los emails de OAuth se marcan como verificados automaticamente
|
|
|
|
### Estructura de Archivos Backend
|
|
|
|
```
|
|
apps/backend/src/modules/auth/
|
|
├── controllers/
|
|
│ └── oauth.controller.ts
|
|
├── services/
|
|
│ └── oauth.service.ts
|
|
├── entities/
|
|
│ ├── oauth-connection.entity.ts
|
|
│ └── oauth-provider.enum.ts
|
|
├── guards/
|
|
│ └── jwt-auth.guard.ts
|
|
└── strategies/
|
|
└── jwt.strategy.ts
|
|
```
|
|
|
|
---
|
|
|
|
## Referencia Template-SaaS
|
|
|
|
Esta epica esta alineada con el modulo SAAS-015 OAuth de template-saas.
|
|
|
|
| Modulo SAAS | Version | Elementos Integrados |
|
|
|-------------|---------|---------------------|
|
|
| SAAS-015 OAuth | 1.0.0 | Endpoints, modelo de datos, flujo OAuth |
|
|
|
|
Ver documentacion fuente en `projects/template-saas/docs/01-modulos/SAAS-015-oauth.md`
|
|
|
|
---
|
|
|
|
**Ultima actualizacion:** 2026-01-13
|
|
**Autor:** Architecture Team
|
|
**Alineacion:** template-saas v1.0.0
|