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:
@@ -188,6 +188,17 @@ const userExpanded = reactive({});
|
||||
const deviceExpanded = reactive({});
|
||||
// formulario inline removido: se usa modal con UserForm
|
||||
|
||||
// Helper para detectar errores de autenticación
|
||||
function isAuthError(error) {
|
||||
// Si es un TypeError de fetch, probablemente es CORS (redirección de Authentik)
|
||||
return error instanceof TypeError && error.message.includes('fetch');
|
||||
}
|
||||
|
||||
function handleAuthError() {
|
||||
console.warn('Sesión expirada o error de autenticación, redirigiendo...');
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
const showEventFilters = ref(false);
|
||||
const showUserFilters = ref(false);
|
||||
const eventFilters = reactive({ text: '', type: '' });
|
||||
@@ -203,8 +214,17 @@ async function fetchUsers() {
|
||||
loading.users = true;
|
||||
try {
|
||||
const res = await fetch('/api/users');
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
||||
}
|
||||
const data = await res.json();
|
||||
users.value = data.items || [];
|
||||
} catch (error) {
|
||||
if (isAuthError(error)) {
|
||||
handleAuthError();
|
||||
} else {
|
||||
console.error('Error fetching users:', error);
|
||||
}
|
||||
} finally { loading.users = false; }
|
||||
}
|
||||
|
||||
@@ -212,17 +232,35 @@ async function fetchRequests() {
|
||||
loading.requests = true;
|
||||
try {
|
||||
const res = await fetch('/api/requests');
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
||||
}
|
||||
const data = await res.json();
|
||||
requests.value = data.items || [];
|
||||
} catch (error) {
|
||||
if (isAuthError(error)) {
|
||||
handleAuthError();
|
||||
} else {
|
||||
console.error('Error fetching requests:', error);
|
||||
}
|
||||
} finally { loading.requests = false; }
|
||||
}
|
||||
|
||||
async function fetchDevices() {
|
||||
try {
|
||||
const res = await fetch('/api/devices');
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
||||
}
|
||||
const data = await res.json();
|
||||
devices.value = data.items || [];
|
||||
} catch {}
|
||||
} catch (error) {
|
||||
if (isAuthError(error)) {
|
||||
handleAuthError();
|
||||
} else {
|
||||
console.error('Error fetching devices:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleDisable(u) {
|
||||
|
||||
Reference in New Issue
Block a user