From 30544b564eb7658c6830ba38a31af856fd6509fc Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Sat, 18 Dec 2021 17:00:02 -0500 Subject: [PATCH] express: Skip express-session middleware if pre-authorized --- src/node/hooks/express.js | 12 ++++++++---- src/node/hooks/express/webaccess.js | 10 ++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/node/hooks/express.js b/src/node/hooks/express.js index 2441b827e..8704835a9 100644 --- a/src/node/hooks/express.js +++ b/src/node/hooks/express.js @@ -202,15 +202,19 @@ exports.restartServer = async () => { }, }); - // If webaccess.preAuthorize explicitly grants access, webaccess.checkAccess will skip all checks. app.use(webaccess.preAuthorize); // Give plugins an opportunity to install handlers/middleware after the preAuthorize middleware // but before the express-session middleware. This allows plugins to avoid creating an // express-session record in the database when it is not needed (e.g., public static content). await hooks.aCallAll('expressPreSession', {app}); - app.use(exports.sessionMiddleware); - app.use(cookieParser(settings.sessionKey, {})); - app.use(webaccess.checkAccess); + app.use([ + // If webaccess.preAuthorize explicitly granted access, webaccess.nextRouteIfPreAuthorized will + // call `next('route')` which will skip the remaining middlewares in this list. + webaccess.nextRouteIfPreAuthorized, + exports.sessionMiddleware, + cookieParser(settings.sessionKey, {}), + webaccess.checkAccess, + ]); await Promise.all([ hooks.aCallAll('expressConfigure', {app}), diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index 42586b757..10e531717 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -200,12 +200,22 @@ const checkAccess = async (req, res, next) => { * Express middleware that allows plugins to explicitly grant/deny access via the `preAuthorize` * hook before `checkAccess` is run. If access is explicitly granted: * - `next('route')` will be called, which can be used to bypass later checks + * - `nextRouteIfPreAuthorized` will simply call `next('route')` * - `checkAccess` will simply call `next('route')` */ exports.preAuthorize = (req, res, next) => { preAuthorize(req, res, next).catch((err) => next(err || new Error(err))); }; +/** + * Express middleware that simply calls `next('route')` if the request has been explicitly granted + * access by `preAuthorize` (otherwise it calls `next()`). This can be used to bypass later checks. + */ +exports.nextRouteIfPreAuthorized = (req, res, next) => { + if (res.locals._webaccess.skip) return next('route'); + next(); +}; + /** * Express middleware to authenticate the user and check authorization. Must be installed after the * express-session middleware. If the request is pre-authorized, this middleware simply calls