Solucionar errores de CORS manteniendo seguridad de Authentik
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 46s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 46s
PROBLEMA: - Frontend hacía fetch a APIs protegidas por Authentik - Cuando sesión expiraba, Authentik redirigía causando error de CORS - TypeError: Failed to fetch SOLUCIÓN: 1. Backend inyecta window.__AUTHENTIK_USER__ en HTML inicial (app.js) - Servidor lee headers de Authentik y los pasa al frontend - Evita fetch innecesario en carga inicial 2. Frontend usa window.__AUTHENTIK_USER__ como fuente principal (useAuthentik.js) - Solo hace fetch cuando se fuerza refresh - Detecta errores de CORS como señal de sesión expirada - Muestra mensaje claro al usuario 3. App.vue detecta errores de autenticación en APIs - Cuando fetch falla con CORS, recarga página automáticamente - Authentik manejará la re-autenticación SEGURIDAD: - Todos los endpoints /api/* siguen protegidos por Authentik - No se exponen APIs sin autenticación - Headers de Authentik solo presentes con sesión válida
This commit is contained in:
@@ -2,6 +2,7 @@ import express from 'express';
|
||||
import morgan from 'morgan';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { readFileSync } from 'fs';
|
||||
import apiRouter from './routes/api.js';
|
||||
import radiusRouter from './routes/radius.js';
|
||||
import authRouter from './routes/auth.js';
|
||||
@@ -27,8 +28,44 @@ export function createApp() {
|
||||
// Simple health endpoint for reverse proxies / checks
|
||||
app.get('/healthz', (_req, res) => res.json({ ok: true }));
|
||||
|
||||
app.get('/', (_req, res) => {
|
||||
res.sendFile(path.join(__dirname, '..', 'public', 'index.html'));
|
||||
// Servir index.html con información de usuario inyectada
|
||||
app.get('/', (req, res) => {
|
||||
const indexPath = path.join(__dirname, '..', 'public', 'index.html');
|
||||
let html = readFileSync(indexPath, 'utf-8');
|
||||
|
||||
// Leer headers de Authentik
|
||||
const username = req.headers['x-authentik-username'];
|
||||
const email = req.headers['x-authentik-email'];
|
||||
const name = req.headers['x-authentik-name'];
|
||||
const groups = req.headers['x-authentik-groups'];
|
||||
const uid = req.headers['x-authentik-uid'];
|
||||
|
||||
// Crear objeto de usuario
|
||||
const userData = username ? {
|
||||
authenticated: true,
|
||||
user: {
|
||||
username,
|
||||
email,
|
||||
name,
|
||||
groups: groups ? groups.split('|').filter(g => g.trim()) : [],
|
||||
uid
|
||||
}
|
||||
} : {
|
||||
authenticated: false,
|
||||
user: null
|
||||
};
|
||||
|
||||
// Inyectar en el HTML antes de </head>
|
||||
const injection = `
|
||||
<script>
|
||||
window.__AUTHENTIK_USER__ = ${JSON.stringify(userData)};
|
||||
</script>
|
||||
</head>`;
|
||||
|
||||
html = html.replace('</head>', injection);
|
||||
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.send(html);
|
||||
});
|
||||
|
||||
return app;
|
||||
|
||||
Reference in New Issue
Block a user