--- id: "US-AUTH-006" title: "OAuth Apple Sign In" type: "User Story" status: "To Do" priority: "Alta" epic: "OQI-001" story_points: 3 created_date: "2025-12-05" updated_date: "2026-01-04" --- # US-AUTH-006: OAuth Apple Sign In **Version:** 1.0.0 **Fecha:** 2025-12-05 **Estado:** Pendiente **Story Points:** 3 **Prioridad:** P1 (Alta) **Épica:** [OQI-001](../_MAP.md) --- ## Historia de Usuario **Como** visitante o usuario de Trading Platform **Quiero** poder registrarme e iniciar sesión usando Apple Sign In **Para** tener un acceso seguro y privado sin compartir mi email real --- ## Criterios de Aceptación ### AC-001: Botón de Apple visible **Dado** que estoy en la página de registro o login **Cuando** veo las opciones de autenticación **Entonces** debería ver un botón "Continuar con Apple" **Y** debería seguir las guías de diseño de Apple (botón negro con logo) ### AC-002: Flujo de OAuth **Dado** que hago click en "Continuar con Apple" **Cuando** se abre la ventana de Apple **Entonces** debería: 1. Ver la pantalla de autorización de Apple 2. Poder elegir compartir mi email real o ocultarlo 3. Poder usar Touch ID / Face ID si está disponible 4. Poder autorizar con mi Apple ID ### AC-003: Opción de ocultar email **Dado** que estoy en la pantalla de Apple Sign In **Cuando** elijo ocultar mi email **Entonces** Apple debería generar un email relay privado **Y** ese email debería funcionar para comunicaciones ### AC-004: Primer registro exitoso **Dado** que es mi primera vez usando Apple Sign In **Cuando** autorizo los permisos **Entonces** debería: 1. Crear mi cuenta automáticamente 2. Recibir un JWT token 3. Ser redirigido al dashboard 4. Ver mi nombre de Apple (si lo compartí) 5. Email verificado automáticamente ### AC-005: Login existente **Dado** que ya tengo una cuenta vinculada con Apple **Cuando** uso "Continuar con Apple" **Entonces** debería: 1. Iniciar sesión automáticamente 2. Usar Touch ID / Face ID si está configurado 3. Ser redirigido al dashboard ### AC-006: Email relay de Apple **Dado** que usé la opción de ocultar mi email **Cuando** la aplicación envía emails **Entonces** debería enviarlos al email relay de Apple **Y** Apple debería reenviarlos a mi email real **Y** debería poder responder a través del relay ### AC-007: Datos mínimos recibidos **Dado** que autorizo Apple Sign In **Cuando** completo el flujo **Entonces** la app debería recibir: - `user_id` único de Apple - Email (real o relay) - Nombre (opcional, solo primera vez) **Y** NO debería recibir otra información personal ### AC-008: Revocación de acceso **Dado** que revoco el acceso desde configuración de Apple **Cuando** intento hacer login nuevamente **Entonces** debería ver un error de autorización **Y** debería poder re-autorizar la aplicación --- ## Mockup ``` ┌─────────────────────────────────────────────────────────────┐ │ │ │ 🌟 Bienvenido a Trading Platform │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 📧 Email │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 🔴 Continuar con Google │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ Continuar con Apple │ │ │ └─────────────────────────────────────────────────────┘ │ │ (Botón negro con logo de Apple blanco) │ │ │ │ [Facebook] [Twitter/X] [GitHub] │ │ │ └─────────────────────────────────────────────────────────────┘ Ventana de Apple Sign In: ┌─────────────────────────────────────────────────────────────┐ │ appleid.apple.com ✕ │ ├─────────────────────────────────────────────────────────────┤ │ │ │ │ │ │ │ "Trading Platform" desea usar tu Apple ID para iniciar sesión │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ Nombre │ │ │ │ ○ Compartir mi nombre │ │ │ │ ○ No compartir │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ Email │ │ │ │ ○ Compartir mi email (juan@icloud.com) │ │ │ │ ● Ocultar mi email │ │ │ │ (se usará: xyz123@privaterelay.appleid.com) │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ Tu información será compartida según las políticas de │ │ privacidad de Trading Platform. │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ Continuar con Touch ID │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ Cancelar │ │ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Tareas Técnicas ### Database (DB) - [ ] Agregar campos a tabla `users`: ```sql ALTER TABLE users ADD COLUMN apple_id VARCHAR(255) UNIQUE; ALTER TABLE users ADD COLUMN is_private_email BOOLEAN DEFAULT false; ``` - [ ] Usar tabla `oauth_connections` existente - [ ] Índice en `apple_id` ### Backend (BE) - [ ] Configurar Apple Developer Account - [ ] Crear App ID y Service ID - [ ] Generar y configurar private key (.p8) - [ ] Endpoint `GET /api/v1/auth/apple` - Redirige a Apple Sign In - [ ] Endpoint `POST /api/v1/auth/apple/callback` - Recibe ID Token (JWT) - Valida firma del token con Apple public key - Decodifica user info - Maneja primera autorización (recibe nombre) - Crea o actualiza usuario - Genera JWT token - [ ] Service `AppleOAuthService` - `getAuthorizationUrl()` - `validateIdToken()` - `decodeUserInfo()` - `linkAccount()` - [ ] Librería: `apple-signin-auth` o similar - [ ] Tests unitarios (8 casos) - [ ] Tests de integración con mock ### Frontend (FE) - [ ] Botón "Sign in with Apple" (siguiendo guías de Apple) - [ ] Manejo de popup/redirect OAuth - [ ] Recepción de callback - [ ] Almacenamiento de token JWT - [ ] Estado de loading - [ ] Manejo de errores - [ ] Tests con React Testing Library ### Testing (QA) - [ ] E2E: Registro con Apple (email real) - [ ] E2E: Registro con Apple (email oculto) - [ ] E2E: Login existente - [ ] E2E: Revocación y re-autorización - [ ] Test de validación de ID Token - [ ] Test de seguridad: Firma del token - [ ] Test de seguridad: CSRF protection - [ ] Mock de Apple ID Token --- ## Dependencias - **Bloqueantes:** - Apple Developer Account ($99/año) - Dominio verificado en Apple - Configuración de Service ID - Private key (.p8) generada - SSL/HTTPS en producción - **Deseables:** - US-AUTH-003: Consistencia con otros OAuth --- ## Definition of Ready (DoR) - [ ] Apple Developer Account activa - [ ] Service ID configurado - [ ] Private key generada y segura - [ ] Mockups aprobados siguiendo Apple HIG - [ ] API contract definido - [ ] Dominio verificado en Apple --- ## Definition of Done (DoD) - [ ] Código implementado y revisado - [ ] Tests unitarios con 80%+ cobertura - [ ] Tests de integración pasando - [ ] Tests E2E implementados - [ ] Botón cumple con Apple guidelines - [ ] Validación de ID Token implementada - [ ] Manejo de email relay funcional - [ ] Documentación actualizada - [ ] Logs implementados - [ ] QA aprobado en staging - [ ] Deploy a producción exitoso --- ## Notas Técnicas ### Apple Sign In Flow 1. Frontend redirige a `/api/v1/auth/apple` 2. Backend redirige a Apple con: - `client_id` (Service ID) - `redirect_uri` - `response_type=code id_token` - `response_mode=form_post` - `scope=name email` - `state` (CSRF token) 3. Usuario autoriza en Apple 4. Apple envía POST a `redirect_uri` con: - `id_token` (JWT firmado) - `code` (authorization code) - `user` (solo primera vez, contiene nombre) 5. Backend valida ID Token con Apple public key 6. Backend decodifica user info 7. Backend crea/actualiza usuario 8. Backend genera JWT y redirige a frontend ### Apple ID Token Structure ```json { "iss": "https://appleid.apple.com", "aud": "com.trading.service", "exp": 1234567890, "iat": 1234567890, "sub": "001234.abc123...", // Apple User ID "email": "xyz@privaterelay.appleid.com", "email_verified": true, "is_private_email": true, "nonce_supported": true } ``` ### Environment Variables ```env APPLE_SERVICE_ID=com.trading.service APPLE_TEAM_ID=ABC123XYZ APPLE_KEY_ID=KEY123 APPLE_PRIVATE_KEY_PATH=/path/to/AuthKey_KEY123.p8 APPLE_CALLBACK_URL=https://trading.com/api/v1/auth/apple/callback ``` ### Consideraciones Especiales de Apple - Apple solo envía nombre en la primera autorización - Email relay de Apple es permanente por app - ID Token está firmado con RS256 - Requiere validar firma con Apple public keys - Response mode debe ser `form_post` (no query params) - Requiere HTTPS estricto - No hay refresh tokens en el flujo web ### Security Considerations - Validar firma del ID Token con Apple public key - Verificar `aud` claim coincide con Service ID - Validar `iss` es `https://appleid.apple.com` - Verificar `exp` no está expirado - Validar `state` parameter (CSRF) - Guardar nombre solo en primera autorización - Logs de autenticación ### Apple Design Guidelines - Usar botón oficial "Sign in with Apple" - Color negro en tema claro, blanco en tema oscuro - Logo de Apple siempre visible - Texto específico según contexto - Mismo tamaño que otros botones OAuth --- ## Requerimientos Relacionados - [RF-AUTH-003: OAuth Social](../requerimientos/RF-AUTH-003-oauth.md) ## Especificaciones Relacionadas - [ET-AUTH-002: JWT Tokens](../especificaciones/ET-AUTH-002-jwt.md) - [ET-AUTH-004: OAuth Integration](../especificaciones/ET-AUTH-004-oauth.md)