--- id: "SAAS-015" title: "OAuth 2.0 Endpoints" type: "Module" status: "Completed" priority: "P1" module: "oauth" version: "1.0.0" created_date: "2026-01-24" updated_date: "2026-01-24" story_points: 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) ```sql - 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 ```sql 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:** ```json { "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:** ```json { "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:** ```json { "message": "Provider unlinked successfully" } ``` #### GET /auth/oauth/connections Lista todas las conexiones OAuth del usuario. **Headers:** Authorization: Bearer {jwt} **Response:** ```json { "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 ```json { "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 ```env # 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 - [Google OAuth 2.0](https://developers.google.com/identity/protocols/oauth2) - [Microsoft Identity Platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/) - [GitHub OAuth](https://docs.github.com/en/developers/apps/building-oauth-apps) - [Apple Sign-In](https://developer.apple.com/sign-in-with-apple/) --- *SAAS-015 v1.0.0 - Template SaaS*