Reputation: 549
I am trying to redirect back to the page when I am redirected to log in. I am using Passport and connect-ensure-login, and the login works, however, it gets annoying having to re-click the link (if you are not logged in, it redirects you to the home page, but the link has a query string). Is there a way to add a redirect URL upon successful log-in?
The redirect URL needs to be dynamic, because it is query strings, and is not dependent upon the user's id or anything like that.
Here is a snippet of my server-side code (please tell me if you need any other snippets because my app.js is 224 lines long and I don't want to post that).
app.js
:
let express = require( 'express' );
let app = express();
const expressSession = require('express-session')({
secret: `secret`,
resave: false,
saveUninitialized: false
});
app.use(expressSession);
const passport = require('passport');
app.use(passport.initialize());
app.use(passport.session());
let path = require( 'path' );
const passportLocalMongoose = require('passport-local-mongoose');
const connectEnsureLogin = require('connect-ensure-login');
var mongoose = require("mongoose");
var bodyParser = require("body-parser");
const Mixed = mongoose.Schema.Types.Mixed;
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/db', { useNewUrlParser: true, useUnifiedTopology: false });
const Schema = mongoose.Schema;
const UserDetail = new Schema({
username: String,
email: Mixed,
password: String,
verified: Boolean
});
UserDetail.plugin(passportLocalMongoose);
const UserDetails = mongoose.model('userInfo', UserDetail, 'userInfo');
passport.use(UserDetails.createStrategy());
passport.serializeUser(UserDetails.serializeUser());
passport.deserializeUser(UserDetails.deserializeUser());
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }));
app.use( '/login', express.static( path.join( __dirname, 'login' ) ) );
app.get( '/', connectEnsureLogin.ensureLoggedIn(), ( req, res ) => {
res.sendFile( __dirname + '/index.html' );
});
app.post('/login', (req, res, next) => {
passport.authenticate('local',
(err, user, info) => {
if (err) {
return next(err);
}
if (!user) {
return res.redirect('/login?info=' + info);
}
req.logIn(user, function(err) {
if (err) {
return next(err);
}
return res.redirect('/');
});
})(req, res, next);
});
app.get('/login', (req, res) => {
res.sendFile('login/login.html', { root: __dirname })
});
app.get('/register', (req, res) => {
res.sendFile('login/register.html', { root: __dirname })
});
app.get('/user', connectEnsureLogin.ensureLoggedIn(), (req, res) => {
res.send({user: req.user})
})
app.post('/register', (req, res) =>{
UserDetails.register({ username: req.body.username, active: false, email: req.body.email }, req.body.password)
res.redirect('/login')
})
Is there a way to:
connectEnsureLogin.ensureLoggedIn()
?I'm new to Node.js so I followed an example to get the Login to work (sorry, I do not have the example now, I don't know where I found it and I didn't save a copy of it).
Also, this question does not duplicate this SO question because I cannot think of how to implement the answer with my current middleware, connectEnsureLogin.ensureLoggedIn(). If not, please tell me how I can implement @Chovy's answer to use my current situation.
Thanks so much!!!!
I think it has something to do with redirectTo
in connectEnsureLogin, however, I cannot get it to read the query string. I tried to set redirectTo
to req.url
but my servers errors with:
returnTo: req.query
^
ReferenceError: req is not defined
Is there a way to do this? Thanks
Upvotes: 1
Views: 1147
Reputation: 2097
Sadly, connectEnsureLogin
does not provide the customizations needed in your case, however, a simple middleware function does exactly what you want.
At the top, define a middleware function and set a session cookie called RedirectTo:
function auth (req, res, next) {
if (req.isAuthenticated()) {
// user is authenticated, so we do not need to redirect them.
return next();
} else {
// user is not authenticated, so add a session cookie telling our server where to redirect to.
req.session.redirectTo = req.url;
// redirect to login with cookie set
res.redirect('/login');
}
}
You can use the middleware like this:
app.get( '/', auth, ( req, res ) => {
// ^^^^ notice that we use our middleware instead
res.sendFile( __dirname + '/index.html' );
})
Then, you can read that session cookie in your post request handler like this:
app.post('/login', (req, res, next) => {
// authentication like normal
passport.authenticate('local',(err, user, info) => {
if (err) {
return next(err);
}
if (!user) {
return res.redirect('/login?info=' + info);
}
req.logIn(user, function(err) {
if (err) {
return next(err);
}
// this is the special part
// redirect the user to the session cookie if it exists
var redirectTo = req.session.redirectTo || '/';
// delete the session cookie so it is not present on the next request
delete req.session.redirectTo;
// redirecting the user to where they want to go
res.redirect(redirectTo || '/');
});
})(req, res, next);
});
Upvotes: 1