Redirigir a la página anterior después de la autenticación en node.js usando passport.js

Estoy tratando de establecer un mecanismo de inicio de sesión usando node.js, express y passport.js. El inicio de sesión en sí funciona bastante bien, también las sesiones se almacenan bien con redis, pero tengo algunos problemas para redirigir al usuario a donde comenzó antes de que se me solicite la autenticación.

por ejemplo, el usuario sigue el enlace http://localhost:3000/hidden luego se redirige a http://localhost:3000/login pero luego quiero que sea redirigido nuevamente a http://localhost:3000/hidden .

El propósito de esto es que si el usuario accede aleatoriamente a una página en la que necesita iniciar sesión primero, será redirigido al sitio / login que proporciona sus credenciales y luego será redirigido al sitio al que intentó acceder anteriormente.

Aquí está mi entrada de inicio de sesión

 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 Asegurarse Autenticado

 function ensureAuthenticated (req, res, next) { if (req.isAuthenticated()) { return next(); } res.redirect('/login'); } 

que se engancha en la /hidden 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.

  

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 redirigir 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 || '/'; delete req.session.redirectTo; // is authenticated ? res.redirect(redirectTo); 

En su método ensureAuthenticated , guarde la URL de retorno en la sesión de la siguiente manera:

 ... req.session.returnTo = req.path; res.redirect('/login'); ... 

Luego puede actualizar su ruta de pasaporte. Autenticación a algo como:

 app.get('/auth/google/return', passport.authenticate('google'), function(req, res) { res.redirect(req.session.returnTo || '/'); delete req.session.returnTo; }); 

Eche un vistazo a connect-garantizar-login , que funciona junto con Passport para hacer exactamente lo que quiere.

Si está utilizando connect-sure-login, hay una forma muy sencilla e integrada de hacer esto con Passport usando el parámetro successReturnToOrRedirect . Cuando se use, el pasaporte lo enviará de vuelta a la URL solicitada originalmente o se remitirá a la URL que proporcionó.

 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

Mi forma de hacer las cosas:

 const isAuthenticated = (req, res, next) => { if (req.isAuthenticated()) { return next() } res.redirect( `/login?origin=${req.originalUrl}` ) }; 

Controlador GET / login :

 if( req.query.origin ) req.session.returnTo = req.query.origin else req.session.returnTo = req.header('Referer') res.render('account/login') 

POST / controlador de 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 si hay un 100% de autorización, los comentarios son bienvenidos):

 req.logout(); res.redirect(req.header('Referer') || '/'); if (req.session.returnTo) { delete req.session.returnTo } 

Clear backTo middleware (borra returnTo de la sesión en cualquier ruta, excepto las rutas de autenticación, 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 :

  • puede proteger algunas rutas con isAuthenticated middleware;
  • en cualquier página , simplemente puede hacer clic en la URL de inicio de sesión, y después de iniciar sesión vuelva a esa página;

Las respuestas de @chovy y @linuxdan tienen un error al no borrar session.returnTo si el usuario va a otra página después de la redirección de inicio de sesión (eso no requiere autenticación) e inicia sesión allí. Entonces 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 en ensureAuthenticated de ensureAuthenticated

 req.flash('redirectTo', req.path) res.redirect('/login') 

Y luego en GET login

 res.render('login', { redirectTo: req.flash('redirectTo') }) 

En la vista, agregue un 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 del primer inicio de sesión GET con él.

La forma más fácil (y adecuada) de lograr esto es establecer las opciones failureRedirect y successRedirect .