Seguridad y autenticación - Josecgh/diagAuto-frontend GitHub Wiki

Autenticación (Authentication)

El backend emite un token JWT que se almacena en cookies con el atributo httpOnly. El frontend nunca lee ni guarda el token: el servicio de autenticación (AuthService) solo conserva los datos del usuario y sus propiedades de suscripción (isPremium) devueltos por el endpoint /auth/me.

sequenceDiagram
    participant U as Usuario
    participant F as Frontend (Angular)
    participant B as Backend (REST API)
    U->>F: Envía formulario de login
    F->>B: POST /api/v1/auth/login
    B-->>F: 200 + Set-Cookie (httpOnly JWT) + cookie XSRF-TOKEN
    F->>B: GET /api/v1/auth/me
    B-->>F: Datos de usuario + Estado de suscripción
    F->>F: AuthService guarda los datos en un Angular Signal (sin token)
    U->>F: Navega a la Agenda o intenta añadir un coche
    F->>F: Las Guardas de Ruta comprueban la sesión y el límite Freemium
    F->>B: Petición HTTP con cookies automáticas + cabecera X-XSRF-TOKEN
    B-->>F: 200 / 401 / 403

Por qué usamos cookies en lugar de localStorage

  • Una cookie httpOnly no puede ser leída por JavaScript, lo que blinda la aplicación ante vulnerabilidades XSS que intenten robar la sesión.
  • El navegador envía las cookies de forma automática en cada petición de red (withCredentials: true).
  • Las cookies están configuradas como Secure y SameSite=None, motivo por el cual tanto el frontend como el backend deben ejecutarse bajo HTTPS en entornos de desarrollo.

Protección contra ataques XSRF

Dado que la sesión viaja automáticamente en las cookies, el backend exige un token de validación contra falsificación de peticiones en sitios cruzados (XSRF). En Angular, esto se gestiona de forma nativa configurando el cliente global HttpClient en el archivo de proveedores de la aplicación:

// src/app/app.config.ts
import { provideHttpClient, withXsrfConfiguration } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(
      withXsrfConfiguration({
        cookieName: 'XSRF-TOKEN',
        headerName: 'X-XSRF-TOKEN'
      })
    )
  ]
};

Renovación automática de sesión

Un interceptor HTTP funcional captura los tokens expirados en segundo plano para que el usuario no sufra interrupciones en su flujo de trabajo:

flowchart TD
    A[Respuesta con error HTTP] --> B{Código de Estado}
    B -->|403| F[Manejo del 403: Redirigir al Paywall por límite de coches]
    B -->|Otros errores| R[Rechazar y propagar el error]
    B -->|401| C{¿La petición era el Login?}
    C -->|Sí| R
    C -->|No| D{¿Ya se está renovando?}
    D -->|Sí| Q[Encolar la petición hasta que termine la renovación]
    D -->|No| E[GET /auth/refresh]
    E -->|Éxito / OK| G[Reintentar la petición original + las encoladas]
    E -->|Falla| H[Limpiar Signal de sesión y redirigir a /login]

Autorización (Guardas de Ruta)

El sistema de enrutamiento (src/app/app.routes.ts) protege los accesos mediante guardas funcionales (CanActivateFn) basadas en el estado reactivo de las Angular Signals:

  • URL desconocida o no registrada: Los usuarios anónimos van a Login y los autenticados a su Dashboard / Agenda.
  • Intento de acceso privado sin sesión: Redirección inmediata al formulario de Login.
  • Usuario autenticado intenta entrar a páginas de invitados (/login, /register): Se cancela el acceso y se le envía de vuelta a su Dashboard.
  • Intento de añadir un 5.º vehículo en el Plan Básico: La guarda detecta que se ha alcanzado el límite (myVehicles().length >= 4) e intercepta la navegación desviando al usuario hacia el Paywall.

Las guardas de ruta mejoran la experiencia de usuario y la fluidez de la interfaz, pero la seguridad real la impone el backend: cada endpoint protegido valida la sesión del propietario en el servidor.