Add comprehensive documentation for components, Traefik and Authentik

- Document all authentication components architecture
  - UserAvatar, UserMetadata components
  - Individual action buttons with their specific functionality
  - useAuthentik() composable with full API documentation

- Explain Authentik Proxy Outpost flow
  - Forward Auth mechanism
  - Step-by-step authentication flow
  - Advantages of proxy-based authentication

- Detail Traefik routing configuration
  - Router 1: Public routes (PWA resources) with priority 100
  - Router 2: Protected routes with Authentik middleware
  - CORS and headers middleware explanation

- Add complete Authentik setup guide
  - Traefik middleware configuration
  - Authentik Provider and Application setup
  - Network configuration requirements

- Include troubleshooting section
  - Common errors and solutions
  - PWA offline functionality
  - Headers debugging
This commit is contained in:
2025-10-13 03:11:46 -06:00
parent 3f5c4bc820
commit 65dee7382f

244
README.md
View File

@@ -52,6 +52,60 @@ Este proyecto incluye hooks de Claude Code para monitorear automáticamente las
📖 Ver documentación completa en [`.claude/hooks/README.md`](.claude/hooks/README.md) 📖 Ver documentación completa en [`.claude/hooks/README.md`](.claude/hooks/README.md)
## Arquitectura de Componentes
### Componentes de Autenticación
La aplicación utiliza componentes Vue modulares para manejar la autenticación:
#### 1. **UserAvatar** (`app/components/auth/UserAvatar.vue`)
- Muestra el avatar del usuario (generado por UI Avatars)
- Información básica: nombre/username, email y UID
- Se renderiza solo cuando el usuario está autenticado
#### 2. **UserMetadata** (`app/components/auth/UserMetadata.vue`)
- Card detallada con todos los metadatos del usuario
- Muestra: username, email, nombre completo, UID y grupos
- Incluye badges para visualizar los grupos del usuario
#### 3. **Botones de Acción** (componentes individuales)
Cada botón es un componente independiente con su propia lógica:
- **SessionStatusButton**: Verifica el estado de la sesión contra Authentik
- Hace una petición a `/api/auth/status`
- Muestra notificaciones toast con el resultado
- Maneja casos offline y errores de conexión
- **ProfileButton**: Redirige al perfil de usuario en Authentik
- Abre el panel de usuario de Authentik en nueva pestaña
- URL: `{authentikUrl}/if/user/`
- **LogoutButton**: Cierra sesión en Authentik
- Invalida la sesión en todas las aplicaciones
- Redirige a: `{authentikUrl}/flows/-/default/invalidation/`
- **LoginButton**: Fuerza re-autenticación
- Recarga la página para activar el flujo de login de Authentik
### Composable `useAuthentik()`
Composable centralizado para manejar autenticación (`app/composables/useAuthentik.ts`):
**Funcionalidades:**
- Lee headers de Authentik en el servidor (SSR)
- Almacena información del usuario en `useState` (compartido entre cliente/servidor)
- Proporciona funciones reactivas: `user`, `isAuthenticated`
- Métodos: `logout()`, `goToProfile()`, `checkSessionStatus()`
**Headers leídos del Proxy:**
```typescript
X-authentik-username // Nombre de usuario
X-authentik-email // Email
X-authentik-name // Nombre completo
X-authentik-groups // Grupos (separados por |)
X-authentik-uid // ID único del usuario
```
## Despliegue ## Despliegue
El proyecto incluye Gitea Actions que automáticamente: El proyecto incluye Gitea Actions que automáticamente:
@@ -79,39 +133,181 @@ Para configurar el despliegue automático, ve a tu repositorio en Gitea:
📄 Ver ejemplo completo en [`.env.example`](.env.example) 📄 Ver ejemplo completo en [`.env.example`](.env.example)
### Configuración de Authentik Proxy Outpost ## Configuración de Traefik y Authentik
Esta plantilla requiere un **Authentik Proxy Outpost** ya configurado en Traefik. ### 🔐 Cómo Funciona Authentik Proxy Outpost
Authentik Proxy Outpost actúa como un **Forward Auth** middleware que intercepta todas las peticiones antes de que lleguen a tu aplicación:
```
Usuario → Traefik → Authentik Forward Auth → Aplicación Nuxt
↓ (si no auth)
Redirect a Login
```
**Flujo de autenticación:**
1. **Usuario hace petición** → Traefik recibe la petición a tu dominio
2. **Traefik consulta Authentik** → Envía la petición al middleware de Forward Auth
3. **Authentik valida sesión:**
- ✅ **Con sesión válida**: Authentik agrega headers con info del usuario y envía la petición a tu app
- ❌ **Sin sesión**: Authentik redirige al usuario al flujo de login
4. **Tu app recibe la petición** → Con headers de usuario ya inyectados (SSR)
**Ventajas:**
- ✅ No necesitas implementar OAuth en tu app
- ✅ La autenticación se maneja completamente fuera de tu código
- ✅ Los headers llegan automáticamente en cada petición SSR
- ✅ Funciona con cualquier framework (Nuxt, Next.js, PHP, etc.)
### 🚦 Configuración de Reglas de Traefik
El `docker-compose.yml` configura **dos routers** en Traefik para balancear seguridad y funcionalidad PWA:
#### Router 1: Rutas Públicas (Sin Autenticación) - Prioridad 100
```yaml
# Rutas que NO requieren autenticación
- PathPrefix(`/manifest.webmanifest`) # Manifest PWA
- PathPrefix(`/sw.js`) # Service Worker
- PathPrefix(`/workbox-`) # Workbox (PWA)
- PathPrefix(`/icon-`) # Iconos de la app
- PathPrefix(`/apple-touch-icon`) # Icono iOS
- PathPrefix(`/favicon.ico`) # Favicon
- PathPrefix(`/robots.txt`) # SEO
- PathPrefix(`/offline.html`) # Página offline PWA
- PathPrefix(`/api/_nuxt_icon/`) # API de iconos de Nuxt
```
**Middlewares aplicados:**
- `${APP_NAME}-headers`: Headers personalizados (X-Forwarded-Proto)
- `${APP_NAME}-cors`: Configuración CORS para recursos públicos
**¿Por qué sin autenticación?**
- Los Service Workers necesitan acceso sin auth para funcionar offline
- Los manifests PWA deben ser públicos para instalación
- Prioridad 100 asegura que estas rutas se evalúen primero
#### Router 2: Aplicación Protegida (Con Autenticación) - Prioridad 10
```yaml
# Todas las demás rutas (Host match)
Host(`${APP_DOMAIN}`)
```
**Middlewares aplicados:**
- `authentik-forward-auth@file`: Forward Auth de Authentik
- `${APP_NAME}-headers`: Headers personalizados
**Características:**
- Prioridad menor (10) → se evalúa después de las rutas públicas
- Cualquier ruta no pública pasa por autenticación
- Authentik inyecta headers con información del usuario
### 📋 Configuración de Authentik Proxy Outpost
**Requisitos previos:** **Requisitos previos:**
- Red `traefik-network` creada y Traefik corriendo en ella - Traefik corriendo con las redes `traefik-network` y `principal`
- Authentik Forward Auth middleware configurado en Traefik (ej: en `dynamic/middlewares.yml`) - Authentik instalado y funcionando
- Proxy Provider de tipo Forward Auth en Authentik
**Pasos:** **Pasos de configuración:**
1. **En Authentik:** #### 1. Crear el Middleware en Traefik
- Crea una aplicación para tu dominio
- Crea/usa un Proxy Provider de tipo **Forward auth (single application)**
- Asocia la aplicación al Outpost
2. **Redes requeridas:** Crea o edita el archivo de configuración dinámica de Traefik (ej: `dynamic/middlewares.yml`):
- `principal` - Red de tu infraestructura
- `traefik-network` - Red donde corre Traefik
3. **Middleware en Traefik:** ```yaml
- El `docker-compose.yml` usa `authentik-forward-auth@file` http:
- Verifica que este middleware esté definido en tu configuración de Traefik middlewares:
- Si tu middleware tiene otro nombre, actualiza el `docker-compose.yml` authentik-forward-auth:
forwardAuth:
address: http://authentik-server:9000/outpost.goauthentik.io/auth/traefik
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
```
4. **Headers disponibles en la app:** **Importante:** Cambia `authentik-server` por el nombre de tu contenedor/servicio de Authentik.
- `X-authentik-username`: nombre de usuario
- `X-authentik-email`: email del usuario
- `X-authentik-name`: nombre completo
- `X-authentik-groups`: grupos (separados por `|`)
- `X-authentik-uid`: ID único
Tu aplicación Nuxt puede leer estos headers para obtener información del usuario autenticado. #### 2. Configurar Authentik
**a) Crear un Proxy Provider:**
- Ve a **Admin > Applications > Providers**
- Click en **Create**
- Tipo: **Proxy Provider**
- Configuración:
- **Name**: `Mi App - Forward Auth`
- **Authorization flow**: Selecciona tu flujo (ej: `default-provider-authorization-implicit-consent`)
- **Type**: `Forward auth (single application)`
- **External host**: `https://miapp.ejemplo.com` (tu dominio)
**b) Crear una Application:**
- Ve a **Admin > Applications > Applications**
- Click en **Create**
- Configuración:
- **Name**: `Mi App`
- **Slug**: `mi-app`
- **Provider**: Selecciona el provider creado arriba
**c) Vincular al Outpost:**
- Ve a **Admin > Outposts > Outposts**
- Edita tu Outpost (o crea uno nuevo si no existe)
- En **Applications**: Agrega la aplicación creada
#### 3. Configurar las Redes en Docker Compose
Tu aplicación necesita estar en ambas redes:
```yaml
networks:
principal: # Red de tu infraestructura
external: true
traefik-network: # Red donde corre Traefik
external: true
```
Asegúrate de que estas redes existan:
```bash
docker network create principal
docker network create traefik-network
```
### 🔍 Headers Disponibles en tu Aplicación
Una vez configurado, Authentik inyecta estos headers en cada petición:
| Header | Descripción | Ejemplo |
|--------|-------------|---------|
| `X-authentik-username` | Nombre de usuario | `nucleo000` |
| `X-authentik-email` | Email del usuario | `user@example.com` |
| `X-authentik-name` | Nombre completo | `John Doe` |
| `X-authentik-groups` | Grupos (separados por `\|`) | `admins\|users` |
| `X-authentik-uid` | ID único del usuario | `703cae063c59...` |
**En Nuxt**, estos headers se leen automáticamente en SSR mediante `useRequestHeaders()`.
### 🐛 Troubleshooting
**Problema: "Cannot find name 'process'"**
- ✅ Usa `import.meta.server` en lugar de `process.server` (Nuxt 4)
**Problema: Redirect loop infinito**
- Verifica que el middleware `authentik-forward-auth@file` esté correctamente configurado
- Revisa que la aplicación esté asociada al Outpost en Authentik
- Comprueba que el External host coincida con tu dominio
**Problema: Headers no llegan a la aplicación**
- Verifica que `authResponseHeaders` incluya todos los headers necesarios
- Asegúrate de que estés leyendo headers en SSR (`import.meta.server`)
**Problema: PWA no funciona offline**
- Verifica que las rutas públicas tengan prioridad 100
- Confirma que `/sw.js`, `/manifest.webmanifest` y `/offline.html` estén en el router público
## Licencia ## Licencia