template-saas/docs/01-modulos/SAAS-015-oauth.md
Adrian Flores Cortes a6489b0caf
Some checks are pending
CI / Backend CI (push) Waiting to run
CI / Frontend CI (push) Waiting to run
CI / Security Scan (push) Waiting to run
CI / CI Summary (push) Blocked by required conditions
[TASK-2026-01-24] docs: Add SAAS-015, SAAS-016, SAAS-017 specifications
2026-01-24 22:01:59 -06:00

8.0 KiB

id title type status priority module version created_date updated_date story_points
SAAS-015 OAuth 2.0 Endpoints Module Specified P1 oauth 1.0.0 2026-01-24 2026-01-24 5

SAAS-015: OAuth 2.0 Endpoints

Metadata

  • Codigo: SAAS-015
  • Modulo: OAuth (extension de Auth)
  • Prioridad: P1
  • Estado: Especificado
  • Fase: 2 - Integraciones
  • Story Points: 5

Descripcion

Implementacion completa de endpoints OAuth 2.0 para autenticacion federada con multiples proveedores. Permite a los usuarios autenticarse usando sus cuentas de Google, Microsoft, GitHub o Apple.

Nota: La tabla DDL auth.oauth_connections ya existe. Este modulo completa la implementacion backend y frontend.

Objetivos

  1. Autenticacion via Google OAuth 2.0
  2. Autenticacion via Microsoft OAuth 2.0
  3. Autenticacion via GitHub OAuth 2.0
  4. Autenticacion via Apple Sign-In
  5. Vincular/desvincular cuentas OAuth a usuarios existentes
  6. Gestion de conexiones OAuth del usuario

Alcance

Incluido

  • Flujo OAuth completo para 4 proveedores
  • Passport.js strategies para cada proveedor
  • Callback handling con creacion/vinculacion de usuario
  • Gestion de conexiones OAuth por usuario
  • Refresh de tokens OAuth cuando expiran
  • UI para login con proveedores
  • UI para gestionar conexiones en perfil

Excluido

  • SSO/SAML (enterprise feature - SAAS-E01)
  • OAuth como proveedor (ser IdP) - futuro
  • Proveedores adicionales (LinkedIn, Twitter) - bajo demanda

Modelo de Datos

Tablas Existentes (schema: auth)

oauth_connections (DDL ya existe)

- id: UUID PRIMARY KEY
- user_id: UUID REFERENCES users.users(id)
- provider: oauth_provider ENUM ('google', 'microsoft', 'github', 'apple')
- provider_user_id: VARCHAR(255) NOT NULL
- access_token: TEXT
- refresh_token: TEXT
- token_expires_at: TIMESTAMPTZ
- profile_data: JSONB
- created_at: TIMESTAMPTZ DEFAULT NOW()
- updated_at: TIMESTAMPTZ DEFAULT NOW()

UNIQUE(provider, provider_user_id)
UNIQUE(user_id, provider)

ENUMs Existentes

CREATE TYPE auth.oauth_provider AS ENUM (
  'google',
  'microsoft',
  'github',
  'apple'
);

Endpoints API

Metodo Endpoint Descripcion Auth
GET /auth/oauth/:provider Iniciar flujo OAuth No
GET /auth/oauth/:provider/callback Callback del proveedor No
POST /auth/oauth/link/:provider Vincular a cuenta existente JWT
DELETE /auth/oauth/:provider Desvincular proveedor JWT
GET /auth/oauth/connections Listar conexiones del usuario JWT

Detalle de Endpoints

GET /auth/oauth/:provider

Inicia el flujo OAuth redirigiendo al proveedor.

Parametros:

  • provider: google | microsoft | github | apple
  • redirect_uri (query): URL de retorno post-auth

Response: Redirect 302 a URL del proveedor

GET /auth/oauth/:provider/callback

Procesa el callback del proveedor OAuth.

Query params:

  • code: Authorization code del proveedor
  • state: State para validar CSRF

Response:

{
  "access_token": "jwt_token",
  "refresh_token": "refresh_token",
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "name": "Usuario"
  },
  "is_new_user": true
}

POST /auth/oauth/link/:provider

Vincula un proveedor OAuth a la cuenta actual.

Headers: Authorization: Bearer {jwt}

Response:

{
  "message": "Provider linked successfully",
  "connection": {
    "provider": "google",
    "email": "user@gmail.com",
    "linked_at": "2026-01-24T12:00:00Z"
  }
}

DELETE /auth/oauth/:provider

Desvincula un proveedor OAuth de la cuenta.

Headers: Authorization: Bearer {jwt}

Response:

{
  "message": "Provider unlinked successfully"
}

GET /auth/oauth/connections

Lista todas las conexiones OAuth del usuario.

Headers: Authorization: Bearer {jwt}

Response:

{
  "connections": [
    {
      "provider": "google",
      "email": "user@gmail.com",
      "linked_at": "2026-01-24T12:00:00Z"
    },
    {
      "provider": "github",
      "username": "user123",
      "linked_at": "2026-01-20T10:00:00Z"
    }
  ]
}

Implementacion Backend

Entities

  • OAuthConnection - Entity TypeORM para oauth_connections

Services

  • OAuthService - Logica de negocio OAuth
  • OAuthCallbackService - Procesamiento de callbacks

Controllers

  • OAuthController - Endpoints OAuth

Passport Strategies

  • GoogleStrategy - Passport Google OAuth 2.0
  • MicrosoftStrategy - Passport Microsoft OAuth 2.0
  • GitHubStrategy - Passport GitHub OAuth 2.0
  • AppleStrategy - Passport Apple Sign-In

Dependencias NPM

{
  "passport": "^0.7.0",
  "passport-google-oauth20": "^2.0.0",
  "passport-microsoft": "^1.0.0",
  "passport-github2": "^0.1.12",
  "passport-apple": "^2.0.2"
}

Implementacion Frontend

Componentes

  • OAuthButtons - Botones de login OAuth
  • OAuthCallback - Pagina de callback
  • OAuthConnections - Gestion de conexiones en perfil

Paginas

  • /auth/oauth/callback - Procesa callback OAuth

Hooks

  • useOAuthLogin - Iniciar flujo OAuth
  • useOAuthConnections - Gestionar conexiones

Flujos

Login con OAuth (nuevo usuario)

1. Usuario click "Login con Google"
2. Frontend redirige a GET /auth/oauth/google
3. Backend redirige a Google
4. Usuario autoriza en Google
5. Google redirige a /auth/oauth/google/callback
6. Backend:
   a. Valida code con Google
   b. Obtiene perfil del usuario
   c. Crea nuevo User + Tenant
   d. Crea OAuthConnection
   e. Genera JWT tokens
7. Redirect a frontend con tokens
8. Usuario autenticado

Login con OAuth (usuario existente)

1. Usuario click "Login con Google"
2-5. (Mismo flujo)
6. Backend:
   a. Valida code con Google
   b. Busca OAuthConnection existente
   c. Obtiene User vinculado
   d. Genera JWT tokens
7. Redirect a frontend con tokens
8. Usuario autenticado

Vincular OAuth a cuenta existente

1. Usuario autenticado va a Perfil > Conexiones
2. Click "Vincular Google"
3. Redirige a Google OAuth
4. Usuario autoriza
5. Backend:
   a. Valida que no existe conexion con ese provider_user_id
   b. Crea OAuthConnection para user actual
6. Muestra conexion en lista

Configuracion

Variables de Entorno

# Google OAuth
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=xxx
GOOGLE_CALLBACK_URL=https://app.example.com/auth/oauth/google/callback

# Microsoft OAuth
MICROSOFT_CLIENT_ID=xxx
MICROSOFT_CLIENT_SECRET=xxx
MICROSOFT_CALLBACK_URL=https://app.example.com/auth/oauth/microsoft/callback

# GitHub OAuth
GITHUB_CLIENT_ID=xxx
GITHUB_CLIENT_SECRET=xxx
GITHUB_CALLBACK_URL=https://app.example.com/auth/oauth/github/callback

# Apple Sign-In
APPLE_CLIENT_ID=xxx
APPLE_TEAM_ID=xxx
APPLE_KEY_ID=xxx
APPLE_PRIVATE_KEY=xxx
APPLE_CALLBACK_URL=https://app.example.com/auth/oauth/apple/callback

Seguridad

  1. CSRF Protection: Usar state parameter en flujo OAuth
  2. Token Storage: Encriptar access/refresh tokens en BD
  3. Scope Minimo: Solicitar solo email y perfil basico
  4. Validacion de Dominio: Verificar callback URL contra whitelist
  5. Rate Limiting: Limitar intentos de OAuth por IP

Criterios de Aceptacion

  • Login con Google funciona end-to-end
  • Login con Microsoft funciona end-to-end
  • Login con GitHub funciona end-to-end
  • Login con Apple funciona end-to-end
  • Usuario puede vincular multiples proveedores
  • Usuario puede desvincular proveedores (si tiene password o otro provider)
  • Conexiones se muestran en perfil
  • Tests unitarios con cobertura >70%
  • Tests E2E para flujo completo

Dependencias

  • SAAS-001 (Auth) - Base de autenticacion
  • SAAS-003 (Users) - Gestion de usuarios

Referencias


SAAS-015 v1.0.0 - Template SaaS