Sicherheit: - CSRF-Schutz auf allen API-Routes (admin, proposals, files, stats, export) - authenticateToken vor csrfProtection bei admin/proposals (CSRF-Bypass behoben) - CORS eingeschränkt auf taskmate.aegis-sight.de - JWT_SECRET und SESSION_TIMEOUT nicht mehr exportiert - Tote Auth-Funktionen entfernt (generateCsrfToken, generateToken Legacy) Toter Code entfernt: - 6 ungenutzte JS-Dateien (tour, dashboard, 4x contacts-*) - 2 ungenutzte CSS-Dateien (dashboard, contacts-extended) - backend/migrations/ Verzeichnis, knowledge.js.backup - Doppelter bcrypt require in database.js Optimierung: - Request-Logging filtert statische Assets (nur /api/ wird geloggt) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
103 Zeilen
3.4 KiB
JavaScript
103 Zeilen
3.4 KiB
JavaScript
/**
|
|
* TASKMATE - Auth Fix
|
|
* ====================
|
|
* Behebt Authentifizierungs-Probleme
|
|
*/
|
|
|
|
// Überwache alle API-Anfragen
|
|
const originalFetch = window.fetch;
|
|
window.fetch = async function(...args) {
|
|
try {
|
|
const response = await originalFetch.apply(this, args);
|
|
|
|
// Bei 401: Automatisches Token-Refresh versuchen
|
|
if (response.status === 401 && !args[0].includes('/auth/login')) {
|
|
console.log('[AuthFix] 401 erkannt, versuche Token-Refresh...');
|
|
|
|
const token = localStorage.getItem('token');
|
|
const refreshToken = localStorage.getItem('refreshToken');
|
|
|
|
if (token) {
|
|
try {
|
|
// Versuche Token-Refresh
|
|
const refreshResponse = await originalFetch('/api/auth/refresh', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${token}`
|
|
},
|
|
body: JSON.stringify({ refreshToken: refreshToken || token })
|
|
});
|
|
|
|
if (refreshResponse.ok) {
|
|
const data = await refreshResponse.json();
|
|
console.log('[AuthFix] Token erfolgreich erneuert');
|
|
|
|
// Neue Tokens speichern
|
|
localStorage.setItem('token', data.token);
|
|
if (data.refreshToken) {
|
|
localStorage.setItem('refreshToken', data.refreshToken);
|
|
}
|
|
|
|
// Original-Request mit neuem Token wiederholen
|
|
if (args[1] && args[1].headers) {
|
|
args[1].headers['Authorization'] = `Bearer ${data.token}`;
|
|
}
|
|
|
|
return originalFetch.apply(this, args);
|
|
}
|
|
} catch (error) {
|
|
console.error('[AuthFix] Token-Refresh fehlgeschlagen:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
return response;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
// Stelle sicher, dass das Token bei jedem Request aktuell ist
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
console.log('[AuthFix] Auth-Fix geladen');
|
|
|
|
// Prüfe Token-Gültigkeit alle 5 Minuten
|
|
setInterval(() => {
|
|
const token = localStorage.getItem('token');
|
|
if (token) {
|
|
// Dekodiere JWT um Ablaufzeit zu prüfen
|
|
try {
|
|
const payload = JSON.parse(atob(token.split('.')[1]));
|
|
const expiresIn = payload.exp * 1000 - Date.now();
|
|
|
|
// Wenn Token in weniger als 10 Minuten abläuft, erneuere es
|
|
if (expiresIn < 10 * 60 * 1000) {
|
|
console.log('[AuthFix] Token läuft bald ab, erneuere...');
|
|
fetch('/api/auth/refresh', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${token}`
|
|
},
|
|
body: JSON.stringify({ refreshToken: localStorage.getItem('refreshToken') || token })
|
|
}).then(response => {
|
|
if (response.ok) {
|
|
return response.json();
|
|
}
|
|
}).then(data => {
|
|
if (data && data.token) {
|
|
localStorage.setItem('token', data.token);
|
|
if (data.refreshToken) {
|
|
localStorage.setItem('refreshToken', data.refreshToken);
|
|
}
|
|
console.log('[AuthFix] Token automatisch erneuert');
|
|
}
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('[AuthFix] Fehler beim Token-Check:', error);
|
|
}
|
|
}
|
|
}, 5 * 60 * 1000); // Alle 5 Minuten
|
|
}); |