handle case sensitive

This commit is contained in:
2026-04-23 11:58:02 +02:00
parent 8c0e0408d2
commit 12d7de5065
3 changed files with 242 additions and 80 deletions

View File

@@ -118,7 +118,7 @@ const server = https.createServer(httpsOptions, app);
databaseModel.set('authentication', require(`@models/authenticationModel`)(service.get('sqlManager').getInstance('main'))); databaseModel.set('authentication', require(`@models/authenticationModel`)(service.get('sqlManager').getInstance('main')));
service.set('fileSystemManager', new FileSystemManager()); service.set('fileSystemManager', new FileSystemManager());
service.set('authenticationManager', new AuthenticationManager(databaseModel.get('authentication'), app.locals.configuration.integration.token.secret, service.get('eventManager'))); service.set('authenticationManager', new AuthenticationManager(databaseModel.get('authentication'), app.locals.configuration.integration.token.secret));
service.set('activeDirectoryManager', new ActiveDirectory(app.locals.configuration.integration.activedirectory)) service.set('activeDirectoryManager', new ActiveDirectory(app.locals.configuration.integration.activedirectory))
// everytime last created service! // everytime last created service!

View File

@@ -1,80 +1,66 @@
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs'); const bcrypt = require('bcryptjs');
const { fn, col, where } = require('sequelize');
let { levelId, message } = '';
/** /**
* Authentication class for login method, token validation and password setting * Authentication class for login method, token validation and password setting
*/ */
class AuthenticationManager { class AuthenticationManager {
/** constructor(model, secretKey) {
*
* @param {object} model - Use the authentication database model for interact with the database
* @param {string} secretKey - Defines the server secret for token validation
*/
constructor(model, secretKey, eventManager) {
this.eventManager = eventManager;
// if (!model) throw new Error('Sequelize Model wird benötigt');
// if (!secretKey) throw new Error('Secret Key wird benötigt');
this.Authentication = model; this.Authentication = model;
this.SECRET_KEY = secretKey; this.SECRET_KEY = secretKey;
} }
/**
* Helper: Case-insensitive User Lookup
*/
async findUser(sAMAccountName) {
return await this.Authentication.findOne({
where: where(
fn('LOWER', col('sAMAccountName')),
sAMAccountName.toLowerCase()
)
});
}
/** /**
* Set or reset password of user * Set or reset password of user
* @param {string} sAMAccountName - Windows account name
* @param {string} password - Set the new password
*/ */
async setPassword(sAMAccountName, password) { async setPassword(sAMAccountName, password) {
const user = await this.Authentication.findOne({ where: { sAMAccountName } }); const user = await this.findUser(sAMAccountName);
if (!user) { if (!user) {
// this.eventManager.write(null, 2, 0, { aboveLevel: 1 }, `User nicht gefunden`); return { token: null, levelId: 2, message: 'Unbekannter User' };
levelId = 2;
message = `Unbekannter User`
return {token: null, levelId: levelId };
// throw new Error(`User ${sAMAccountName} nicht gefunden`);
} }
// if (user.password) throw new Error('Passwort bereits gesetzt');
const hashedPassword = await bcrypt.hash(password, 10); const hashedPassword = await bcrypt.hash(password, 10);
user.password = hashedPassword; user.password = hashedPassword;
await user.save(); await user.save();
return { token: null, levelId: 0, message: 'Passwort gesetzt' };
} }
/** /**
* Login mit Speicherung des Tokens in der Datenbank * Login
*/ */
async login(sAMAccountName, password) { async login(sAMAccountName, password) {
const user = await this.Authentication.findOne({ where: { sAMAccountName } }); const user = await this.findUser(sAMAccountName);
if (!user) { if (!user) {
//this.eventManager.write(null, 2, null, null, `User ${sAMAccountName} nicht geufunden`) return { token: null, levelId: 2, message: 'Unbekannter Benutzer' };
levelId = 2;
message = `Unbekannter Benutzer`;
return { token: null, levelId: levelId, message: message };
// throw new Error('Unkown user');
} }
if (!user.password) { if (!user.password) {
this.setPassword(sAMAccountName, password); await this.setPassword(sAMAccountName, password);
// this.eventManager.write(user.ObjectGUID, 2, null, null, 'User registration initialized') return { token: null, levelId: 1, message: 'Benutzer nicht registriert' };
levelId = 1;
message = `Benutzer nicht registiert`;
return { token: null, levelId: levelId, message: message };
// throw new Error('User not registered');
} }
const passwordMatch = await bcrypt.compare(password, user.password); const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) { if (!passwordMatch) {
// this.eventManager.write(user.ObjectGUID, 2, null, null, 'Password doesn\'t match'); return { token: null, levelId: 2, message: 'Falsches Passwort' };
levelId = 2;
message = `Falsches Passwort`;
return { token: null, levelId: levelId, message: message };
// throw new Error('Wrong password');
} }
// Token erzeugen
const payload = { const payload = {
sAMAccountName: user.sAMAccountName, sAMAccountName: user.sAMAccountName,
mail: user.mail, mail: user.mail,
@@ -83,90 +69,266 @@ class AuthenticationManager {
}; };
const token = jwt.sign(payload, this.SECRET_KEY, { expiresIn: '100y' }); const token = jwt.sign(payload, this.SECRET_KEY, { expiresIn: '100y' });
// Token in DB speichern
user.refreshtoken = token; user.refreshtoken = token;
user.online = true; user.online = true;
await user.save(); await user.save();
// this.eventManager.write(user.ObjectGUID, 1, null, null, 'Erfolgreich angemeldet'); return {
levelId = 0; token,
message = `Erfolgreich angemeldet`; levelId: 0,
return { token: token, levelId: levelId, message: message }; message: 'Erfolgreich angemeldet'
};
} }
/** /**
* Logout löscht Token aus der DB * Logout
*/ */
async logout(sAMAccountName) { async logout(sAMAccountName) {
const user = await this.Authentication.findOne({ where: { sAMAccountName } }); const user = await this.findUser(sAMAccountName);
if (user) {
if (!user) {
return { token: null, levelId: 2, message: 'User nicht gefunden' };
}
user.refreshtoken = null; user.refreshtoken = null;
user.online = false; user.online = false;
await user.save(); await user.save();
levelId = 0;
message = `Erfolgreich abgemeldet`; return { token: null, levelId: 0, message: 'Erfolgreich abgemeldet' };
return { token: null, levelId: levelId, message: message };
}
} }
/** /**
* Token-Prüfung (über DB) * Token prüfen
*/ */
async verifyUserToken(sAMAccountName) { async verifyUserToken(sAMAccountName) {
const user = await this.Authentication.findOne({ where: { sAMAccountName } }); const user = await this.findUser(sAMAccountName);
if (!user || !user.refreshtoken) { if (!user || !user.refreshtoken) {
levelId = 1, return { valid: false, levelId: 1, message: 'Kein gültiger Token' };
message = `Kein gültiger Token`;
// throw new Error('Kein gespeicherter Token gefunden');
} }
try { try {
const payload = jwt.verify(user.refreshtoken, this.SECRET_KEY); const payload = jwt.verify(user.refreshtoken, this.SECRET_KEY);
levelId = 0;
message = `User verifiziert`; return {
return { valid: true, payload, user, levelId: levelId, message: message } valid: true,
payload,
user,
levelId: 0,
message: 'User verifiziert'
};
} catch { } catch {
levelId = 4; return {
message = `Ungültiger Token`; valid: false,
return { valid: false, payload, user, levelId: levelId, message: message } levelId: 4,
message: 'Ungültiger Token'
};
} }
} }
/** /**
* Express Middleware prüft Token direkt aus DB anhand sAMAccountNamec * Middleware
*/ */
authenticate() { authenticate() {
return async (req, res, next) => { return async (req, res, next) => {
try { try {
const sAMAccountName = req.cookies?.sAMAccountName; const sAMAccountName = req.cookies?.sAMAccountName;
const objectGUID = req.cookies?.ObjectGUID; const objectGUID = req.cookies?.ObjectGUID;
if (!sAMAccountName || !objectGUID) { if (!sAMAccountName || !objectGUID) {
return res.redirect('/login'); return res.redirect('/login');
// return res.status(401).json({ message: 'Kein Benutzer-Cookie gefunden' });
} }
const user = await this.Authentication.findOne({ where: { sAMAccountName } }); const user = await this.findUser(sAMAccountName);
if (!user || !user.refreshtoken) {
if (!user || !user.refreshtoken || user.active === false) {
return res.redirect('/login'); return res.redirect('/login');
// return res.status(401).json({ message: 'Benutzer oder Token nicht gefunden' });
} }
if (user.active === false) { jwt.verify(user.refreshtoken, this.SECRET_KEY);
return res.redirect('/login');
// return res.status(401).json({ message: 'Benutzer ist nicht aktiv' });
}
// Token aus DB prüfen
const payload = jwt.verify(user.refreshtoken, this.SECRET_KEY);
req.user = user; req.user = user;
next(); next();
} catch (err) { } catch (err) {
console.error(err); console.error(err);
return res.redirect('/login'); return res.redirect('/login');
// res.status(401).json({ message: 'Authentifizierung fehlgeschlagen' });
} }
}; };
} }
} }
module.exports = AuthenticationManager; module.exports = AuthenticationManager;
// const jwt = require('jsonwebtoken');
// const bcrypt = require('bcryptjs');
// let { levelId, message } = '';
// /**
// * Authentication class for login method, token validation and password setting
// */
// class AuthenticationManager {
// /**
// *
// * @param {object} model - Use the authentication database model for interact with the database
// * @param {string} secretKey - Defines the server secret for token validation
// */
// constructor(model, secretKey, eventManager) {
// this.eventManager = eventManager;
// // if (!model) throw new Error('Sequelize Model wird benötigt');
// // if (!secretKey) throw new Error('Secret Key wird benötigt');
// this.Authentication = model;
// this.SECRET_KEY = secretKey;
// }
// /**
// * Set or reset password of user
// * @param {string} sAMAccountName - Windows account name
// * @param {string} password - Set the new password
// */
// async setPassword(sAMAccountName, password) {
// const user = await this.Authentication.findOne({ where: { sAMAccountName } });
// if (!user) {
// // this.eventManager.write(null, 2, 0, { aboveLevel: 1 }, `User nicht gefunden`);
// levelId = 2;
// message = `Unbekannter User`
// return {token: null, levelId: levelId };
// // throw new Error(`User ${sAMAccountName} nicht gefunden`);
// }
// // if (user.password) throw new Error('Passwort bereits gesetzt');
// const hashedPassword = await bcrypt.hash(password, 10);
// user.password = hashedPassword;
// await user.save();
// }
// /**
// * Login mit Speicherung des Tokens in der Datenbank
// */
// async login(sAMAccountName, password) {
// const user = await this.Authentication.findOne({ where: { sAMAccountName } });
// if (!user) {
// //this.eventManager.write(null, 2, null, null, `User ${sAMAccountName} nicht geufunden`)
// levelId = 2;
// message = `Unbekannter Benutzer`;
// return { token: null, levelId: levelId, message: message };
// // throw new Error('Unkown user');
// }
// if (!user.password) {
// this.setPassword(sAMAccountName, password);
// // this.eventManager.write(user.ObjectGUID, 2, null, null, 'User registration initialized')
// levelId = 1;
// message = `Benutzer nicht registiert`;
// return { token: null, levelId: levelId, message: message };
// // throw new Error('User not registered');
// }
// const passwordMatch = await bcrypt.compare(password, user.password);
// if (!passwordMatch) {
// // this.eventManager.write(user.ObjectGUID, 2, null, null, 'Password doesn\'t match');
// levelId = 2;
// message = `Falsches Passwort`;
// return { token: null, levelId: levelId, message: message };
// // throw new Error('Wrong password');
// }
// // Token erzeugen
// const payload = {
// sAMAccountName: user.sAMAccountName,
// mail: user.mail,
// givenName: user.givenName,
// sn: user.sn
// };
// const token = jwt.sign(payload, this.SECRET_KEY, { expiresIn: '100y' });
// // Token in DB speichern
// user.refreshtoken = token;
// user.online = true;
// await user.save();
// // this.eventManager.write(user.ObjectGUID, 1, null, null, 'Erfolgreich angemeldet');
// levelId = 0;
// message = `Erfolgreich angemeldet`;
// return { token: token, levelId: levelId, message: message };
// }
// /**
// * Logout löscht Token aus der DB
// */
// async logout(sAMAccountName) {
// const user = await this.Authentication.findOne({ where: { sAMAccountName } });
// if (user) {
// user.refreshtoken = null;
// user.online = false;
// await user.save();
// levelId = 0;
// message = `Erfolgreich abgemeldet`;
// return { token: null, levelId: levelId, message: message };
// }
// }
// /**
// * Token-Prüfung (über DB)
// */
// async verifyUserToken(sAMAccountName) {
// const user = await this.Authentication.findOne({ where: { sAMAccountName } });
// if (!user || !user.refreshtoken) {
// levelId = 1,
// message = `Kein gültiger Token`;
// // throw new Error('Kein gespeicherter Token gefunden');
// }
// try {
// const payload = jwt.verify(user.refreshtoken, this.SECRET_KEY);
// levelId = 0;
// message = `User verifiziert`;
// return { valid: true, payload, user, levelId: levelId, message: message }
// } catch {
// levelId = 4;
// message = `Ungültiger Token`;
// return { valid: false, payload, user, levelId: levelId, message: message }
// }
// }
// /**
// * Express Middleware prüft Token direkt aus DB anhand sAMAccountNamec
// */
// authenticate() {
// return async (req, res, next) => {
// try {
// const sAMAccountName = req.cookies?.sAMAccountName;
// const objectGUID = req.cookies?.ObjectGUID;
// if (!sAMAccountName || !objectGUID) {
// return res.redirect('/login');
// // return res.status(401).json({ message: 'Kein Benutzer-Cookie gefunden' });
// }
// const user = await this.Authentication.findOne({ where: { sAMAccountName } });
// if (!user || !user.refreshtoken) {
// return res.redirect('/login');
// // return res.status(401).json({ message: 'Benutzer oder Token nicht gefunden' });
// }
// if (user.active === false) {
// return res.redirect('/login');
// // return res.status(401).json({ message: 'Benutzer ist nicht aktiv' });
// }
// // Token aus DB prüfen
// const payload = jwt.verify(user.refreshtoken, this.SECRET_KEY);
// req.user = user;
// next();
// } catch (err) {
// console.error(err);
// return res.redirect('/login');
// // res.status(401).json({ message: 'Authentifizierung fehlgeschlagen' });
// }
// };
// }
// }
// module.exports = AuthenticationManager;

View File

@@ -50,7 +50,7 @@ function safeClone(obj) {
const authorized = const authorized =
item.label === 'hr' || item.label === 'hr' ||
item.permissions.includes('Administration') item.permissions.includes('Administration')
? global.json.configuration.live.administration.includes(sAMAccountName) ? global.json.configuration.live.administration.some(name => name.toLowerCase() === sAMAccountName.toLowerCase())
: item.permissions.includes('*') || : item.permissions.includes('*') ||
( (
await Promise.all( await Promise.all(