58 lines
2.1 KiB
TypeScript
58 lines
2.1 KiB
TypeScript
import type { Application } from 'express';
|
|
import basicAuth from 'basic-auth';
|
|
// IMPORTANT! Do not switch to anther bcrypt library unless really necessary and
|
|
// tested with all possible systems like Windows, Alpine on ARM, FreeBSD, ...
|
|
import { compare } from 'bcryptjs';
|
|
import type { Config } from '@/config';
|
|
import { basicAuthAuthorizationError } from '@/ResponseHelper';
|
|
|
|
export const setupBasicAuth = async (app: Application, config: Config, authIgnoreRegex: RegExp) => {
|
|
const basicAuthUser = config.getEnv('security.basicAuth.user');
|
|
if (basicAuthUser === '') {
|
|
throw new Error('Basic auth is activated but no user got defined. Please set one!');
|
|
}
|
|
|
|
const basicAuthPassword = config.getEnv('security.basicAuth.password');
|
|
if (basicAuthPassword === '') {
|
|
throw new Error('Basic auth is activated but no password got defined. Please set one!');
|
|
}
|
|
|
|
const basicAuthHashEnabled = config.getEnv('security.basicAuth.hash');
|
|
|
|
let validPassword: null | string = null;
|
|
|
|
app.use(async (req, res, next) => {
|
|
// Skip basic auth for a few listed endpoints or when instance owner has been setup
|
|
if (authIgnoreRegex.exec(req.url) || config.getEnv('userManagement.isInstanceOwnerSetUp')) {
|
|
return next();
|
|
}
|
|
const realm = 'n8n - Editor UI';
|
|
const basicAuthData = basicAuth(req);
|
|
|
|
if (basicAuthData === undefined) {
|
|
// Authorization data is missing
|
|
return basicAuthAuthorizationError(res, realm, 'Authorization is required!');
|
|
}
|
|
|
|
if (basicAuthData.name === basicAuthUser) {
|
|
if (basicAuthHashEnabled) {
|
|
if (validPassword === null && (await compare(basicAuthData.pass, basicAuthPassword))) {
|
|
// Password is valid so save for future requests
|
|
validPassword = basicAuthData.pass;
|
|
}
|
|
|
|
if (validPassword === basicAuthData.pass && validPassword !== null) {
|
|
// Provided hash is correct
|
|
return next();
|
|
}
|
|
} else if (basicAuthData.pass === basicAuthPassword) {
|
|
// Provided password is correct
|
|
return next();
|
|
}
|
|
}
|
|
|
|
// Provided authentication data is wrong
|
|
return basicAuthAuthorizationError(res, realm, 'Authorization data is wrong!');
|
|
});
|
|
};
|