Add more customization options for authOptions

This commit is contained in:
Mustafa Gezen 2022-07-17 22:16:38 +02:00
parent 95340b21ee
commit 361a9378aa
Signed by untrusted user who does not match committer: mustafa
GPG Key ID: DCDF010D946438C1

View File

@ -53,7 +53,7 @@ const { auth } = expressOidc;
export default async function(opts) { export default async function(opts) {
// Create a new app for health checks. // Create a new app for health checks.
const appZ = express(); const appZ = express();
appZ.get('/_/healthz', ((req, res) => { appZ.get('/healthz', ((req, res) => {
res.end(); res.end();
})); }));
@ -83,15 +83,19 @@ export default async function(opts) {
console.log(`Using clientID: ${opts.clientID}`); console.log(`Using clientID: ${opts.clientID}`);
console.log(`Using baseURL: ${opts.baseURL}`); console.log(`Using baseURL: ${opts.baseURL}`);
if (opts.issuerBaseURL.endsWith('.localhost') || opts.issuerBaseURL.endsWith('.localhost/')) { if ((opts.issuerBaseURL.endsWith('.localhost')
const kong = 'kong-proxy.kong.svc.cluster.local' || opts.issuerBaseURL.endsWith('.localhost/'))
&& process.env['BYC_ENV']) {
const kong = 'kong-proxy.kong.svc.cluster.local';
const urlObject = new URL(opts.issuerBaseURL); const urlObject = new URL(opts.issuerBaseURL);
console.warn(`Forcing ${urlObject.hostname} to resolve to ${kong}`); console.warn(`Forcing ${urlObject.hostname} to resolve to ${kong}`);
const lookup = async () => { const lookup = async () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// noinspection HttpUrlsUsage // noinspection HttpUrlsUsage
dns.lookup(kong, { family: 4 }, (err, address, family) => { dns.lookup(kong, { family: 4 }, (err, address, family) => {
if(err) reject(err); if (err) {
reject(err);
}
resolve(address); resolve(address);
}); });
}); });
@ -99,11 +103,13 @@ export default async function(opts) {
const internalServiceResolve = await lookup(); const internalServiceResolve = await lookup();
evilDns.add(urlObject.hostname, internalServiceResolve); evilDns.add(urlObject.hostname, internalServiceResolve);
// Disable TLS verification for development // Disable TLS verification for development
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0 process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
} }
const config = { const config = {
authRequired: process.env['DISABLE_AUTH_ENFORCE'] ? process.env['DISABLE_AUTH_ENFORCE'] === 'false' : !!!opts.disableAuthEnforce, authRequired: process.env['DISABLE_AUTH_ENFORCE']
? process.env['DISABLE_AUTH_ENFORCE'] === 'false'
: !!!opts.disableAuthEnforce,
// Disable telemetry // Disable telemetry
enableTelemetry: false, enableTelemetry: false,
// Use dev secret is none is present (Prod requires a secret so not a security issue) // Use dev secret is none is present (Prod requires a secret so not a security issue)
@ -115,7 +121,6 @@ export default async function(opts) {
clientID: opts.clientID, clientID: opts.clientID,
// The specific application should supply a dev secret while prod secrets should be set as an env variable // The specific application should supply a dev secret while prod secrets should be set as an env variable
clientSecret: opts.clientSecret, clientSecret: opts.clientSecret,
// We're currently only using the Rocky issuer
issuerBaseURL: opts.issuerBaseURL, issuerBaseURL: opts.issuerBaseURL,
idpLogout: true, idpLogout: true,
authorizationParams: { authorizationParams: {
@ -138,13 +143,50 @@ export default async function(opts) {
// Remember, authentication done here is only for simplicity purposes. // Remember, authentication done here is only for simplicity purposes.
// The authentication token is then passed on to the API. // The authentication token is then passed on to the API.
// Bypassing auth here doesn't accomplish anything. // Bypassing auth here doesn't accomplish anything.
let middlewares = [];
// If requireEmailSuffix is present, let's validate post callback
// that the signed in email ends with a suffix in the allowlist
// Again, a bypass here doesn't accomplish anything.
let requireEmailSuffix = opts.authOptions?.requireEmailSuffix;
if (process.env['AUTH_OPTIONS_REQUIRE_EMAIL_SUFFIX']) {
requireEmailSuffix = process.env['AUTH_OPTIONS_REQUIRE_EMAIL_SUFFIX'].split(
',');
}
if (requireEmailSuffix) {
middlewares.push((req, res, next) => {
const email = req.oidc?.user?.email;
if (!email) {
return next('No email found in the user object');
}
const suffixes = requireEmailSuffix;
let isAllowed = false;
for (const suffix of suffixes) {
if (email.endsWith(suffix)) {
isAllowed = true;
break;
}
}
if (isAllowed) {
next();
} else {
res.redirect(process.env['AUTH_REJECT_REDIRECT_URL']
? process.env['AUTH_REJECT_REDIRECT_URL']
: (opts.authOptions.authRejectRedirectUrl
|| 'https://rockylinux.org'));
}
});
}
app.use((req, res, next) => { app.use((req, res, next) => {
try { try {
auth(config)(req, res, next); auth(config)(req, res, next);
} catch (err) { } catch (err) {
next(err); next(err);
} }
}); }, [middlewares]);
} }
// Currently in dev, webpack is handling all file serving // Currently in dev, webpack is handling all file serving
@ -200,9 +242,11 @@ export default async function(opts) {
// Make it possible to override api url using an env variable. // Make it possible to override api url using an env variable.
// Example: /api can be set with URL_API // Example: /api can be set with URL_API
// Example 2: /manage/api can be set with URL_MANAGE_API // Example 2: /manage/api can be set with URL_MANAGE_API
const prodEnvName = `URL_${x.substr(1).replace('/', '_').toUpperCase()}`; const prodEnvName = `URL_${x.substr(1).replace('/',
'_').toUpperCase()}`;
const apiUrl = prod ? (process.env[prodEnvName] || opts.apis[x].prodApiUrl) : opts.apis[x].devApiUrl; const apiUrl = prod ? (process.env[prodEnvName]
|| opts.apis[x].prodApiUrl) : opts.apis[x].devApiUrl;
createProxyMiddleware({ createProxyMiddleware({
target: apiUrl, target: apiUrl,
@ -265,7 +309,7 @@ export default async function(opts) {
webpackMildCompile(compiler); webpackMildCompile(compiler);
const wdm = webpackDevMiddleware(compiler, { const wdm = webpackDevMiddleware(compiler, {
publicPath: opts.webpackConfig.output.publicPath, publicPath: opts.webpackConfig.output.publicPath
}); });
app.use(history()); app.use(history());
@ -279,7 +323,8 @@ export default async function(opts) {
// For SPAs, the only HTML page is the index page // For SPAs, the only HTML page is the index page
if (res.get('content-type').indexOf('text/html') !== -1) { if (res.get('content-type').indexOf('text/html') !== -1) {
// Run through handlebars compiler with our template parameters // Run through handlebars compiler with our template parameters
newData = hbs.handlebars.compile(data.toString())(templateParams(req)); newData = hbs.handlebars.compile(data.toString())(
templateParams(req));
} else { } else {
// No new data, just return old data // No new data, just return old data
newData = data; newData = data;