185 lines
7.2 KiB
JavaScript
185 lines
7.2 KiB
JavaScript
// Authentifizierungs-Routes
|
|
|
|
const bcrypt = require('bcryptjs');
|
|
const { db } = require('../database');
|
|
const LDAPService = require('../services/ldap-service');
|
|
const { getDefaultRole } = require('../helpers/utils');
|
|
|
|
// Helper-Funktion für UTF-8 Debug-Logging
|
|
function logUsernameEncoding(label, username) {
|
|
if (!username) {
|
|
console.log(`[${label}] Username is null or undefined`);
|
|
return;
|
|
}
|
|
|
|
console.group(`🔍 ${label} - Server Console`);
|
|
console.log('Original String:', username);
|
|
console.log('String Length:', username.length);
|
|
console.log('Type:', typeof username);
|
|
|
|
// UTF-8 Byte-Repräsentation
|
|
const utf8Bytes = Buffer.from(username, 'utf8');
|
|
console.log('UTF-8 Bytes:', Array.from(utf8Bytes));
|
|
console.log('UTF-8 Bytes (Hex):', Array.from(utf8Bytes).map(b => '0x' + b.toString(16).padStart(2, '0')).join(' '));
|
|
|
|
// Einzelne Zeichen analysieren
|
|
console.log('=== Character Analysis ===');
|
|
for (let i = 0; i < username.length; i++) {
|
|
const char = username[i];
|
|
const codePoint = char.codePointAt(0);
|
|
const utf8BytesForChar = Buffer.from(char, 'utf8');
|
|
console.log(`Position ${i}: "${char}" | CodePoint: U+${codePoint.toString(16).toUpperCase().padStart(4, '0')} (${codePoint}) | UTF-8 Bytes: [${Array.from(utf8BytesForChar).join(', ')}]`);
|
|
}
|
|
|
|
// URL-Encoding Test
|
|
console.log('=== URL Encoding Test ===');
|
|
console.log('encodeURIComponent(username):', encodeURIComponent(username));
|
|
console.log('encodeURI(username):', encodeURI(username));
|
|
|
|
console.groupEnd();
|
|
}
|
|
|
|
// Helper-Funktion für erfolgreiche Anmeldung
|
|
function handleSuccessfulLogin(req, res, user, rememberMe = false) {
|
|
// Rollen als JSON-Array parsen
|
|
let roles = [];
|
|
try {
|
|
roles = JSON.parse(user.role);
|
|
if (!Array.isArray(roles)) {
|
|
// Fallback: Falls kein Array, erstelle Array mit vorhandener Rolle
|
|
roles = [user.role];
|
|
}
|
|
} catch (e) {
|
|
// Fallback: Falls kein JSON, erstelle Array mit vorhandener Rolle
|
|
roles = [user.role || 'mitarbeiter'];
|
|
}
|
|
|
|
// Standard-Rolle bestimmen: Immer "mitarbeiter" wenn vorhanden, sonst höchste Priorität
|
|
let defaultRole;
|
|
if (roles.includes('mitarbeiter')) {
|
|
defaultRole = 'mitarbeiter';
|
|
} else {
|
|
defaultRole = getDefaultRole(roles);
|
|
}
|
|
|
|
req.session.userId = user.id;
|
|
req.session.username = user.username;
|
|
req.session.roles = roles;
|
|
req.session.currentRole = defaultRole;
|
|
req.session.firstname = user.firstname;
|
|
req.session.lastname = user.lastname;
|
|
|
|
// Session-Gültigkeit setzen: 30 Tage wenn "Angemeldet bleiben" aktiviert, sonst 24 Stunden
|
|
if (rememberMe) {
|
|
req.session.cookie.maxAge = 30 * 24 * 60 * 60 * 1000; // 30 Tage
|
|
} else {
|
|
req.session.cookie.maxAge = 24 * 60 * 60 * 1000; // 24 Stunden
|
|
}
|
|
|
|
// Redirect: Immer zu Dashboard wenn Mitarbeiter-Rolle vorhanden, sonst basierend auf Standard-Rolle
|
|
if (roles.includes('mitarbeiter')) {
|
|
res.redirect('/dashboard');
|
|
} else if (defaultRole === 'admin') {
|
|
res.redirect('/admin');
|
|
} else if (defaultRole === 'verwaltung') {
|
|
res.redirect('/verwaltung');
|
|
} else {
|
|
res.redirect('/dashboard');
|
|
}
|
|
}
|
|
|
|
// Routes registrieren
|
|
function registerAuthRoutes(app) {
|
|
// Login-Seite
|
|
app.get('/login', (req, res) => {
|
|
res.render('login', { error: null });
|
|
});
|
|
|
|
// Login-Verarbeitung
|
|
app.post('/login', (req, res) => {
|
|
const { username, password, remember_me } = req.body;
|
|
const rememberMe = remember_me === 'on' || remember_me === true;
|
|
|
|
// Debug-Logging: Empfangener Username vom Client
|
|
console.log('\n========== LOGIN REQUEST RECEIVED ==========');
|
|
logUsernameEncoding('Username received from client', username);
|
|
console.log('Request headers content-type:', req.headers['content-type']);
|
|
console.log('Request body keys:', Object.keys(req.body));
|
|
|
|
// Prüfe ob LDAP aktiviert ist
|
|
LDAPService.getConfig((err, ldapConfig) => {
|
|
if (err) {
|
|
console.error('Fehler beim Abrufen der LDAP-Konfiguration:', err);
|
|
}
|
|
|
|
const isLDAPEnabled = ldapConfig && ldapConfig.enabled === 1;
|
|
console.log('LDAP enabled:', isLDAPEnabled);
|
|
|
|
// Wenn LDAP aktiviert ist, authentifiziere gegen LDAP
|
|
if (isLDAPEnabled) {
|
|
console.log('Starting LDAP authentication...');
|
|
LDAPService.authenticate(username, password, (authErr, authSuccess, ldapUserInfo) => {
|
|
console.log('\n========== LDAP AUTHENTICATION RESULT ==========');
|
|
console.log('authErr:', authErr ? authErr.message : null);
|
|
console.log('authSuccess:', authSuccess);
|
|
console.log('ldapUserInfo:', ldapUserInfo);
|
|
|
|
if (authErr || !authSuccess) {
|
|
console.log('LDAP authentication failed, trying local database fallback...');
|
|
logUsernameEncoding('Username for DB fallback lookup', username);
|
|
// LDAP-Authentifizierung fehlgeschlagen - prüfe lokale Datenbank als Fallback
|
|
db.get('SELECT * FROM users WHERE username = ? COLLATE NOCASE', [username], (err, user) => {
|
|
if (err || !user) {
|
|
return res.render('login', { error: 'Ungültiger Benutzername oder Passwort' });
|
|
}
|
|
|
|
if (bcrypt.compareSync(password, user.password)) {
|
|
handleSuccessfulLogin(req, res, user, rememberMe);
|
|
} else {
|
|
res.render('login', { error: 'Ungültiger Benutzername oder Passwort' });
|
|
}
|
|
});
|
|
} else {
|
|
// LDAP-Authentifizierung erfolgreich - Benutzer anhand des kanonischen LDAP-Benutzernamens aus der DB holen
|
|
// (Sync speichert den exakten LDAP-Wert, z. B. "geißlerj" oder "GeisslerJ")
|
|
const dbLookupUsername = (ldapUserInfo && ldapUserInfo.username) ? ldapUserInfo.username : username;
|
|
console.log('LDAP authentication successful!');
|
|
console.log('Original username:', username);
|
|
console.log('Canonical username from LDAP:', dbLookupUsername);
|
|
logUsernameEncoding('Canonical username for DB lookup', dbLookupUsername);
|
|
db.get('SELECT * FROM users WHERE username = ? COLLATE NOCASE', [dbLookupUsername], (err, user) => {
|
|
if (err || !user) {
|
|
return res.render('login', { error: 'Benutzer nicht in der Datenbank gefunden. Bitte führen Sie eine LDAP-Synchronisation durch.' });
|
|
}
|
|
|
|
handleSuccessfulLogin(req, res, user, rememberMe);
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
// LDAP nicht aktiviert - verwende lokale Authentifizierung
|
|
// Case-insensitive Suche: COLLATE NOCASE macht den Vergleich case-insensitive
|
|
db.get('SELECT * FROM users WHERE username = ? COLLATE NOCASE', [username], (err, user) => {
|
|
if (err || !user) {
|
|
return res.render('login', { error: 'Ungültiger Benutzername oder Passwort' });
|
|
}
|
|
|
|
if (bcrypt.compareSync(password, user.password)) {
|
|
handleSuccessfulLogin(req, res, user, rememberMe);
|
|
} else {
|
|
res.render('login', { error: 'Ungültiger Benutzername oder Passwort' });
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// Logout
|
|
app.get('/logout', (req, res) => {
|
|
req.session.destroy();
|
|
res.redirect('/login');
|
|
});
|
|
}
|
|
|
|
module.exports = registerAuthRoutes;
|