--- id: "ET-AUTH-004" title: "API Endpoints for Auth" type: "Specification" status: "Done" rf_parent: "RF-AUTH-002" epic: "OQI-001" version: "1.0" created_date: "2025-12-05" updated_date: "2026-01-04" --- # ET-AUTH-004: Especificación Técnica - API Endpoints **Version:** 1.0.0 **Fecha:** 2025-12-05 **Estado:** ✅ Implementado **Épica:** [OQI-001](../_MAP.md) --- ## Resumen Esta especificación detalla todos los endpoints de la API de autenticación de Trading Platform. --- ## Base URL ``` Production: https://api.trading.com/api/v1 Development: http://localhost:3000/api/v1 ``` --- ## Endpoints Overview | Método | Endpoint | Descripción | Auth | |--------|----------|-------------|------| | POST | `/auth/register` | Registro con email | ❌ | | POST | `/auth/login` | Login con email/password | ❌ | | POST | `/auth/logout` | Cerrar sesión | ✅ | | POST | `/auth/refresh` | Renovar tokens | ❌ | | GET | `/auth/me` | Usuario actual | ✅ | | GET | `/auth/oauth/:provider/url` | URL de OAuth | ❌ | | POST | `/auth/oauth/:provider` | Callback OAuth | ❌ | | DELETE | `/auth/oauth/:provider` | Desvincular OAuth | ✅ | | POST | `/auth/phone/send` | Enviar OTP | ❌ | | POST | `/auth/phone/verify` | Verificar OTP | ❌ | | POST | `/auth/2fa/setup` | Configurar 2FA | ✅ | | POST | `/auth/2fa/enable` | Activar 2FA | ✅ | | POST | `/auth/2fa/verify` | Verificar 2FA | ❌ | | POST | `/auth/2fa/disable` | Desactivar 2FA | ✅ | | POST | `/auth/forgot-password` | Solicitar reset | ❌ | | POST | `/auth/reset-password` | Cambiar password | ❌ | | POST | `/auth/verify-email` | Verificar email | ❌ | | GET | `/auth/sessions` | Listar sesiones | ✅ | | DELETE | `/auth/sessions/:id` | Revocar sesión | ✅ | | DELETE | `/auth/sessions` | Revocar todas | ✅ | --- ## Detalle de Endpoints ### POST /auth/register Registro de nuevo usuario con email y contraseña. **Request:** ```http POST /api/v1/auth/register Content-Type: application/json { "email": "usuario@example.com", "password": "SecurePass123!", "firstName": "Juan", "lastName": "Pérez", "acceptTerms": true } ``` **Response 201:** ```json { "success": true, "message": "Registro exitoso. Revisa tu email para verificar tu cuenta.", "data": { "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "usuario@example.com", "firstName": "Juan", "lastName": "Pérez", "role": "investor", "status": "pending_verification", "emailVerified": false } } } ``` **Errors:** | Code | Error | Descripción | |------|-------|-------------| | 400 | VALIDATION_ERROR | Datos inválidos | | 409 | EMAIL_EXISTS | Email ya registrado | | 429 | RATE_LIMIT | Demasiadas solicitudes | --- ### POST /auth/login Inicio de sesión con email y contraseña. **Request:** ```http POST /api/v1/auth/login Content-Type: application/json { "email": "usuario@example.com", "password": "SecurePass123!" } ``` **Response 200 (sin 2FA):** ```json { "success": true, "data": { "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "usuario@example.com", "firstName": "Juan", "lastName": "Pérez", "role": "investor", "status": "active" }, "tokens": { "accessToken": "eyJhbGciOiJSUzI1NiIs...", "refreshToken": "eyJhbGciOiJSUzI1NiIs...", "expiresIn": 900, "tokenType": "Bearer" } } } ``` **Response 200 (con 2FA):** ```json { "success": true, "data": { "requires2FA": true, "tempToken": "temp_token_for_2fa_verification", "methods": ["totp", "backup_code"] } } ``` **Errors:** | Code | Error | Descripción | |------|-------|-------------| | 401 | INVALID_CREDENTIALS | Email o contraseña incorrectos | | 403 | EMAIL_NOT_VERIFIED | Email no verificado | | 403 | ACCOUNT_LOCKED | Cuenta bloqueada temporalmente | | 403 | ACCOUNT_SUSPENDED | Cuenta suspendida | --- ### POST /auth/logout Cerrar sesión actual. **Request:** ```http POST /api/v1/auth/logout Authorization: Bearer {accessToken} ``` **Response 200:** ```json { "success": true, "message": "Sesión cerrada exitosamente" } ``` --- ### POST /auth/refresh Renovar access token usando refresh token. **Request:** ```http POST /api/v1/auth/refresh Content-Type: application/json { "refreshToken": "eyJhbGciOiJSUzI1NiIs..." } ``` **Response 200:** ```json { "success": true, "data": { "tokens": { "accessToken": "eyJhbGciOiJSUzI1NiIs...", "refreshToken": "eyJhbGciOiJSUzI1NiIs...", "expiresIn": 900, "tokenType": "Bearer" } } } ``` **Errors:** | Code | Error | Descripción | |------|-------|-------------| | 401 | INVALID_TOKEN | Token inválido o expirado | | 401 | TOKEN_REVOKED | Token revocado | --- ### GET /auth/me Obtener información del usuario actual. **Request:** ```http GET /api/v1/auth/me Authorization: Bearer {accessToken} ``` **Response 200:** ```json { "success": true, "data": { "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "usuario@example.com", "phone": "+525512345678", "firstName": "Juan", "lastName": "Pérez", "role": "investor", "status": "active", "emailVerified": true, "phoneVerified": true, "twoFactorEnabled": false, "createdAt": "2025-01-15T10:00:00Z", "profile": { "displayName": "JuanPerez", "avatarUrl": "https://...", "preferredLanguage": "es", "timezone": "America/Mexico_City" }, "oauthProviders": ["google", "github"] } } } ``` --- ### GET /auth/oauth/:provider/url Obtener URL de autorización OAuth. **Request:** ```http GET /api/v1/auth/oauth/google/url?redirectTo=/dashboard ``` **Response 200:** ```json { "success": true, "data": { "authUrl": "https://accounts.google.com/o/oauth2/v2/auth?...", "state": "random_state_token" } } ``` --- ### POST /auth/oauth/:provider Procesar callback de OAuth. **Request:** ```http POST /api/v1/auth/oauth/google Content-Type: application/json { "code": "authorization_code_from_provider", "state": "state_token_from_url" } ``` **Response 200:** ```json { "success": true, "data": { "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "usuario@gmail.com", "firstName": "Juan", "lastName": "Pérez", "isNewUser": false }, "tokens": { "accessToken": "eyJhbGciOiJSUzI1NiIs...", "refreshToken": "eyJhbGciOiJSUzI1NiIs...", "expiresIn": 900, "tokenType": "Bearer" }, "redirectTo": "/dashboard" } } ``` **Errors:** | Code | Error | Descripción | |------|-------|-------------| | 400 | INVALID_STATE | State token inválido | | 400 | CODE_EXPIRED | Código de autorización expirado | | 502 | PROVIDER_ERROR | Error con el proveedor OAuth | --- ### DELETE /auth/oauth/:provider Desvincular proveedor OAuth. **Request:** ```http DELETE /api/v1/auth/oauth/github Authorization: Bearer {accessToken} ``` **Response 200:** ```json { "success": true, "message": "GitHub desvinculado exitosamente" } ``` **Errors:** | Code | Error | Descripción | |------|-------|-------------| | 400 | LAST_AUTH_METHOD | No puedes eliminar tu único método de auth | | 404 | PROVIDER_NOT_LINKED | Proveedor no vinculado | --- ### POST /auth/phone/send Enviar OTP por SMS o WhatsApp. **Request:** ```http POST /api/v1/auth/phone/send Content-Type: application/json { "phone": "+525512345678", "channel": "whatsapp" } ``` **Response 200:** ```json { "success": true, "message": "Código enviado a tu WhatsApp", "data": { "expiresAt": "2025-12-05T10:05:00Z", "retryAfter": 60 } } ``` **Errors:** | Code | Error | Descripción | |------|-------|-------------| | 400 | INVALID_PHONE | Número de teléfono inválido | | 429 | RATE_LIMIT | Demasiadas solicitudes | | 502 | SMS_ERROR | Error al enviar mensaje | --- ### POST /auth/phone/verify Verificar OTP y autenticar. **Request:** ```http POST /api/v1/auth/phone/verify Content-Type: application/json { "phone": "+525512345678", "code": "123456" } ``` **Response 200:** ```json { "success": true, "data": { "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "phone": "+525512345678", "firstName": "Usuario", "lastName": "Nuevo", "isNewUser": true }, "tokens": { "accessToken": "eyJhbGciOiJSUzI1NiIs...", "refreshToken": "eyJhbGciOiJSUzI1NiIs...", "expiresIn": 900, "tokenType": "Bearer" } } } ``` **Errors:** | Code | Error | Descripción | |------|-------|-------------| | 401 | INVALID_CODE | Código incorrecto | | 401 | CODE_EXPIRED | Código expirado | | 429 | TOO_MANY_ATTEMPTS | Demasiados intentos | --- ### POST /auth/2fa/setup Generar secreto TOTP para configuración. **Request:** ```http POST /api/v1/auth/2fa/setup Authorization: Bearer {accessToken} ``` **Response 200:** ```json { "success": true, "data": { "secret": "JBSWY3DPEHPK3PXP", "qrCode": "data:image/png;base64,iVBORw0KGgo...", "otpauthUrl": "otpauth://totp/Trading Platform:usuario@example.com?..." } } ``` --- ### POST /auth/2fa/enable Activar 2FA después de verificar código. **Request:** ```http POST /api/v1/auth/2fa/enable Authorization: Bearer {accessToken} Content-Type: application/json { "code": "123456" } ``` **Response 200:** ```json { "success": true, "message": "2FA activado exitosamente", "data": { "backupCodes": [ "A1B2C3D4", "E5F6G7H8", "I9J0K1L2", "M3N4O5P6", "Q7R8S9T0", "U1V2W3X4", "Y5Z6A7B8", "C9D0E1F2", "G3H4I5J6", "K7L8M9N0" ] } } ``` --- ### POST /auth/2fa/verify Verificar código 2FA durante login. **Request:** ```http POST /api/v1/auth/2fa/verify Content-Type: application/json { "tempToken": "temp_token_from_login", "code": "123456" } ``` **Response 200:** ```json { "success": true, "data": { "user": { ... }, "tokens": { "accessToken": "eyJhbGciOiJSUzI1NiIs...", "refreshToken": "eyJhbGciOiJSUzI1NiIs...", "expiresIn": 900, "tokenType": "Bearer" } } } ``` --- ### POST /auth/2fa/disable Desactivar 2FA. **Request:** ```http POST /api/v1/auth/2fa/disable Authorization: Bearer {accessToken} Content-Type: application/json { "code": "123456" } ``` **Response 200:** ```json { "success": true, "message": "2FA desactivado exitosamente" } ``` --- ### POST /auth/forgot-password Solicitar recuperación de contraseña. **Request:** ```http POST /api/v1/auth/forgot-password Content-Type: application/json { "email": "usuario@example.com" } ``` **Response 200:** ```json { "success": true, "message": "Si el email existe, recibirás instrucciones para recuperar tu contraseña" } ``` --- ### POST /auth/reset-password Cambiar contraseña con token de recuperación. **Request:** ```http POST /api/v1/auth/reset-password Content-Type: application/json { "token": "reset_token_from_email", "password": "NewSecurePass123!" } ``` **Response 200:** ```json { "success": true, "message": "Contraseña actualizada exitosamente" } ``` --- ### POST /auth/verify-email Verificar email con token. **Request:** ```http POST /api/v1/auth/verify-email Content-Type: application/json { "token": "verification_token_from_email" } ``` **Response 200:** ```json { "success": true, "message": "Email verificado exitosamente" } ``` --- ### GET /auth/sessions Listar sesiones activas. **Request:** ```http GET /api/v1/auth/sessions Authorization: Bearer {accessToken} ``` **Response 200:** ```json { "success": true, "data": { "sessions": [ { "id": "session-uuid-1", "device": { "type": "desktop", "browser": "Chrome", "browserVersion": "120.0.0", "os": "Windows", "osVersion": "11" }, "location": { "city": "Ciudad de México", "country": "México", "countryCode": "MX" }, "ipAddress": "189.xxx.xxx.xxx", "lastActivity": "2025-12-05T10:00:00Z", "createdAt": "2025-12-01T08:00:00Z", "isCurrent": true }, { "id": "session-uuid-2", "device": { "type": "mobile", "browser": "Safari", "os": "iOS", "osVersion": "17.1" }, "location": { "city": "Guadalajara", "country": "México" }, "ipAddress": "187.xxx.xxx.xxx", "lastActivity": "2025-12-04T15:30:00Z", "createdAt": "2025-11-28T10:00:00Z", "isCurrent": false } ], "totalCount": 2 } } ``` --- ### DELETE /auth/sessions/:id Revocar sesión específica. **Request:** ```http DELETE /api/v1/auth/sessions/session-uuid-2 Authorization: Bearer {accessToken} ``` **Response 200:** ```json { "success": true, "message": "Sesión cerrada exitosamente" } ``` --- ### DELETE /auth/sessions Revocar todas las demás sesiones. **Request:** ```http DELETE /api/v1/auth/sessions Authorization: Bearer {accessToken} ``` **Response 200:** ```json { "success": true, "message": "Todas las demás sesiones han sido cerradas", "data": { "revokedCount": 3 } } ``` --- ## Formato de Errores Todos los errores siguen el formato estándar: ```json { "success": false, "error": { "code": "ERROR_CODE", "message": "Descripción legible del error", "details": { "field": "Detalle específico del campo si aplica" } } } ``` --- ## Rate Limiting Headers ```http X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1701792060 ``` --- ## Referencias - [OpenAPI Spec](../../../98-standards/openapi/auth.yaml) - [Postman Collection](../../../96-quick-reference/postman/Trading Platform-Auth.json)