| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import csurf from 'csurf';
- import { createHash } from 'crypto';
- import { NextFunction, Request, Response, Router, RouterOptions, json as jsonBodyParser } from 'express';
- import moment from 'moment';
- import { ChatController } from '../../controllers/chat-controller.class';
- import { ControllerPool } from '../../controllers/lib/controller-pool.interface';
- import { AuthenticationException } from '../../model/err/authentication.exception';
- import { SessionHandler } from './session-handler.class';
- const STATIC_USERS = {
- testuser: 'bc2d5cc456b81caa403661411cc72a309c39677d035b74b713a5ba02412d9eff' // pass1234
- };
- export abstract class HandlerBase implements ControllerPool {
- private _router: Router;
- private _chatCtrl?: ChatController;
- constructor(private sessionHandler?: SessionHandler, auth?: boolean, options?: RouterOptions) {
- this._router = Router(options);
- if (this.sessionHandler) {
- this._router.use(this.sessionHandler.handler);
- if (auth) {
- this._router.use(this.authHandler.bind(this));
- }
- }
- }
- public get router(): Router {
- return this._router;
- }
- public get chat(): ChatController {
- if (!this._chatCtrl) {
- this._chatCtrl = new ChatController(this);
- }
- return this._chatCtrl;
- }
- protected avoidCache = (req, res, next) => {
- res.setHeader('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT');
- res.setHeader('Last-Modified', `${moment().format('ddd, DD MMM YYYY HH:mm:ss')} CEST`);
- res.setHeader('Cache-Control', 'no-cache, max-age=0, must-revalidate, no-store');
- res.setHeader('Pragma', 'no-cache');
- next();
- };
- protected csrf(options?: { ignorePath: string[] }) {
- options = {
- ignorePath: [],
- ...options
- };
- return (req, res, next) => {
- if (options.ignorePath.includes(req.path)) {
- return next();
- }
- csurf({
- ignoreMethods: ['GET', 'HEAD', 'OPTIONS']
- })(req, res, (err?: any) => {
- if (err) return next(err);
- const proto = req.get('x-forwarded-proto') || req.protocol;
- res.cookie('XSRF-TOKEN', req.csrfToken(), {
- httpOnly: false,
- secure: proto === 'https',
- sameSite: 'strict'
- });
- next();
- });
- };
- }
- private async authHandler(
- req: Request<any, any, any, any, Record<string, any>>,
- res: Response<any, Record<string, any>>,
- next: NextFunction
- ): Promise<void> {
- // Is there already a recovered session available -> skip auth handling
- if (req.session && req.session.user) {
- return next();
- }
- // Login Requests Handling
- let loginUser, loginPass;
- if (req.method === 'POST' && req.body && req.body.user && req.body.password) {
- // JSON Post Body Login
- loginUser = req.body.user;
- loginPass = req.body.password;
- } else if (process.env.ENABLE_BASIC_AUTH && req.header('Authorization')?.substring(0, 5).toLowerCase() === 'basic') {
- // Basic Auth Login ( ^- Enable only for DEV)
- [loginUser, loginPass] = Buffer.from(req.header('Authorization').substring(6), 'base64').toString().split(':');
- if (!process.env.UNIT_TEST_MODE) console.log('[INFO]', 'Authenticating via Basic Auth: ', loginUser);
- }
- if (loginUser && loginPass) {
- try {
- // --------------------------------------------- //
- // TODO: Implement your "real" login here.
- // This is just an example implementation based
- // on a STATIC_USERS array defined above ;)
- // --------------------------------------------- //
- const pass = STATIC_USERS[loginUser];
- if (pass && pass === HandlerBase.hashPassword(loginPass)) {
- req.session.user = loginUser; // Hint: you can even store complex object types in a session, not just a string
- req.session.save();
- return next();
- }
- } catch (e) {
- return next(e);
- }
- }
- next(new AuthenticationException('No Session / Session Expired'));
- }
- public static hashPassword(password: string, salt?: string): string {
- if (!salt) {
- salt = process.env.PASSWORD_SALT;
- }
- return createHash('sha256').update(`${salt}${password}`).digest('hex');
- }
- }
|