handle case sensitive
This commit is contained in:
@@ -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!
|
||||||
|
|||||||
@@ -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) {
|
|
||||||
user.refreshtoken = null;
|
if (!user) {
|
||||||
user.online = false;
|
return { token: null, levelId: 2, message: 'User nicht gefunden' };
|
||||||
await user.save();
|
|
||||||
levelId = 0;
|
|
||||||
message = `Erfolgreich abgemeldet`;
|
|
||||||
return { token: null, levelId: levelId, message: message };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user.refreshtoken = null;
|
||||||
|
user.online = false;
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
return { token: null, levelId: 0, message: 'Erfolgreich abgemeldet' };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
|
|||||||
2
utils.js
2
utils.js
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user