Disable Middleware When Redirecting
Solution 1:
I'm assuming this is part of the same problem as here where the real problem is that you want to force authentication before certain admin routes and then after that auth is successful you want to redirect back to the admin route that was originally requested and when your Express handler processes that admin route, it needs to know that it doesn't need to force auth now because auth was just done.
My suggestion would be to use your Express session for that.
Here are the overall steps:
In your
/admin
routes, you create a middlewarecheckAdminPassword()
that checks to see if the password has very recently been verified (more on this later). If not, it redirects to a password page and prefills in that password page form in a hidden field, the original desired URL destination.In the password processing route, you validate the password and you set into the express session object the time that you validated the route.
You then use the original user destination (that was included in the password form in a hidden field) to redirect the user back to their original destination after successful password verification.
Then, when the
/admin
route gets hit again, it calls thecheckAdminPassword()
middleware. This time, that middleware looks in the session object and sees that the password was just verified, a few seconds ago. Since it was just freshly verified, it doesn't prompt again and lets the user through to the admin route.
Here are a examples of some code in a couple of these pieces. Here, when this matches, it sets the verification in the session and sets the current time and then it redirects to the redirectTarget (hidden field from the form).
// Validate password, admin re-enter password to get access to /admin routes
router.post('/validate-password', async (req, res, next) => {
const password = req.body.password;
const match = await passwordController.comparePassword(password, req.user.password);
console.log(password);
if (match) {
// set the time of last password verification
req.session.passwordVerifiedTime = Date.now();
res.redirect(req.body.redirectTarget).
} else {
// return res.render('changePassword', {role_id: req.user.role_id});
req.session.passwordVerifiedTime = 0;
// pass the target for redirection after successful password so this template// can insert that in a hidden field in the password formreturn res.render('validatePassword', {message: 'Wrong password', target: req.session.redirectAfterAuthUrl});
}
});
Then, I'd get rid of the router.all('/admin/*', ...)
route as you don't need that. In any /admin
route that you want this extra verification, you can just add middleware to that route or if you have a whole route of these routes, you can add the middleware just to the router.
router.get('/admin/register', checkAdminPassword, (req, res) => {
res.render('register', {message: req.flash('message'), role_id: req.user.role_id})
});
functioncheckAdminPassword(req, res, next) {
const adminPasswordExpiration = 30 * 1000; // 30 seconds, you can set it to whatever you wantconst now = Date.now();
if (req.session.passwordVerifiedTime && (now - req.session.passwordverified < adminPasswordExpiration)) {
next();
} else {
// admin password verification either not set or expired// remember our desired target location
req.session.redirectAfterAuthUrl = req.url;
res.redirect("/validate-password");
}
}
Solution 2:
Express uses the order you put your end points in to determine where to go. So going to /admin/register matches /admin/*, so Express uses that endpoint. If you switch the order of those two endpoints, it will go to the correct /admin/register function on your redirect.
router.get('/admin/register', (req, res) => {
res.render('register', {message: req.flash('message'), role_id: req.user.role_id})
});
router.all('/admin/*', isAdmin, (req, res, next) => {
res.render('validatePassword', {message: 'Please re-enter your password to get access to ' + req.originalUrl, redirectRoute: req.originalUrl});
// next();
});
Post a Comment for "Disable Middleware When Redirecting"