Redireccionando a la página anterior después de la autenticación en node.js usando passport.js
authentication redirect (7)
Estoy intentando establecer un mecanismo de inicio de sesión usando node.js, express y passport.js. El inicio de sesión funciona bastante bien, también las sesiones se guardan muy bien con redis, pero tengo algunos problemas para redirigir al usuario a donde comenzó antes de que se le pida que autentique.
por ejemplo, el usuario sigue el enlace http://localhost:3000/hidden
luego se redirige a http://localhost:3000/login
pero luego quiero que se lo redirija de nuevo a http://localhost:3000/hidden
.
El objetivo de esto es que si el usuario accede aleatoriamente a una página en la que necesita iniciar sesión primero, se le redirigirá al sitio de inicio de sesión proporcionando sus credenciales y luego será redirigido al sitio al que previamente intentó acceder.
Aquí está mi entrada
app.post(''/login'', function (req, res, next) {
passport.authenticate(''local'', function (err, user, info) {
if (err) {
return next(err)
} else if (!user) {
console.log(''message: '' + info.message);
return res.redirect(''/login'')
} else {
req.logIn(user, function (err) {
if (err) {
return next(err);
}
return next(); // <-? Is this line right?
});
}
})(req, res, next);
});
y aquí mi método garantizado autenticado
function ensureAuthenticated (req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect(''/login'');
}
que se engancha en la página /hidden
app.get(''/hidden'', ensureAuthenticated, function(req, res){
res.render(''hidden'', { title: ''hidden page'' });
});
La salida html para el sitio de inicio de sesión es bastante simple
<form method="post" action="/login">
<div id="username">
<label>Username:</label>
<input type="text" value="bob" name="username">
</div>
<div id="password">
<label>Password:</label>
<input type="password" value="secret" name="password">
</div>
<div id="info"></div>
<div id="submit">
<input type="submit" value="submit">
</div>
</form>
Eche un vistazo a connect-ensure-login , que funciona junto con Passport para hacer exactamente lo que quiere.
En su método ensureAuthenticated
, guarde la URL de retorno en la sesión de esta manera:
...
req.session.returnTo = req.path;
res.redirect(''/login'');
...
Luego puede actualizar su pasaporte. Autenticar la ruta a algo como:
app.get(''/auth/google/return'', passport.authenticate(''google''), function(req, res) {
res.redirect(req.session.returnTo || ''/'');
delete req.session.returnTo;
});
La forma más fácil (y adecuada) de lograr esto es establecer las opciones de successRedirect
failureRedirect
y successRedirect
.
Las respuestas de @chovy y @linuxdan tienen un error al no borrar la session.returnTo
si el usuario va a otra página después de redirigir el inicio de sesión (eso no requiere autenticación) e inicia sesión allí. Así que agrega este código a sus implementaciones:
// clear session.returnTo if user goes to another page after redirect to login
app.use(function(req, res, next) {
if (req.path != ''/login'' && req.session.returnTo) {
delete req.session.returnTo
}
next()
})
Si realiza algunas solicitudes ajax desde la página de inicio de sesión, también puede excluirlas.
Otro enfoque es utilizar flash para ensureAuthenticated
req.flash(''redirectTo'', req.path)
res.redirect(''/login'')
Y luego en GET login
res.render(''login'', { redirectTo: req.flash(''redirectTo'') })
A la vista, agregue el campo oculto al formulario de inicio de sesión (ejemplo en jade)
if (redirectTo != '''')
input(type="hidden" name="redirectTo" value="#{redirectTo}")
En el inicio de sesión POST
res.redirect(req.body.redirectTo || ''/'')
Observe que redirectTo se borrará después de que GET inicie sesión con él.
Mi forma de hacer las cosas:
const isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return next()
}
res.redirect( `/login?origin=${req.originalUrl}` )
};
GET / controlador de inicio de sesión
if( req.query.origin )
req.session.returnTo = req.query.origin
else
req.session.returnTo = req.header(''Referer'')
res.render(''account/login'')
Controlador de POST / inicio de sesión :
let returnTo = ''/''
if (req.session.returnTo) {
returnTo = req.session.returnTo
delete req.session.returnTo
}
res.redirect(returnTo);
Controlador POST / logout (no estoy seguro de si hay un 100% de aceptación, los comentarios son bienvenidos):
req.logout();
res.redirect(req.header(''Referer'') || ''/'');
if (req.session.returnTo) {
delete req.session.returnTo
}
Borrar returnTo middleware (borra returnTo de la sesión en cualquier ruta excepto en auth routes - para mí son / login y / auth /: provider):
String.prototype.startsWith = function(needle)
{
return(this.indexOf(needle) == 0)
}
app.use(function(req, res, next) {
if ( !(req.path == ''/login'' || req.path.startsWith(''/auth/'')) && req.session.returnTo) {
delete req.session.returnTo
}
next()
})
Este enfoque tiene dos características :
- puedes proteger algunas rutas con middleware autenticado ;
- en cualquier página puede simplemente hacer clic en la URL de inicio de sesión y, después de iniciar sesión, volver a esa página;
No sé sobre el pasaporte, pero así es como lo hago:
Tengo un middleware que uso con app.get(''/account'', auth.restrict, routes.account)
que establece redirectTo
en la sesión ... luego me redirecciona a / login
auth.restrict = function(req, res, next){
if (!req.session.userid) {
req.session.redirectTo = ''/account'';
res.redirect(''/login'');
} else {
next();
}
};
Luego en routes.login.post
hago lo siguiente:
var redirectTo = req.session.redirectTo ? req.session.redirectTo : ''/'';
delete req.session.redirectTo;
// is authenticated ?
res.redirect(redirectTo);
Si está utilizando connect-ensure-login hay una forma integrada muy fácil de hacerlo con Passport utilizando el parámetro successReturnToOrRedirect
. Cuando se usa, el pasaporte lo enviará de regreso a la URL solicitada originalmente o se recurrirá a la URL que proporcione.
router.post(''/login'', passport.authenticate(''local'', {
successReturnToOrRedirect: ''/user/me'',
failureRedirect: ''/user/login'',
failureFlash: true
}));
https://github.com/jaredhanson/connect-ensure-login#log-in-and-return-to