How can I tell to EJS if user is logged in? - node.js

I'm trying to check if a user is logged in to display specifc content. I have this:
app.get('/profile', isLoggedIn, (req, res) => {
res.render('profile', {
user: req.user, isLoggedIn: isLoggedIn()
});
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next(null, true);
}
res.redirect('/');
}
And as template:
<%if (isLoggedIn) { %>
<div>Content 1</div>
<% } %>
But I get this error:
Cannot read property 'isAuthenticated' of undefined
What am I doing wrong?

isAuthenticated of undefined meaning req is undefined.
here you are doing mistake.
user: req.user, isLoggedIn: isLoggedIn()
You can not call middleware function like this. isLoggedIn()
What you can do is:
app.get('/profile', isLoggedIn, (req, res) => {
res.render('profile', {
user: req.user, isLoggedIn: req.isLogged
});
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
req.isLogged = true
return next();
}
res.redirect('/');
}

isLoggedIn function is a middleware. It doesn't returns true or false here and you should simply use req.isAuthenticated() that returns true or false if the user is authenticated or not. Here is code :-
app.get('/profile', isLoggedIn, (req, res) => {
res.render('profile', {
user: req.user, isLoggedIn:req.isAuthenticated()
});
});

A simpler way is to just look at whether the variable user is defined.
res.render('profile', {
user: req.user
});
and in your view:
<% if(typeof user != 'undefined') { %>
// do stuff
<% } %>

Related

Why the (req, res, function() {...}) immediately after passport.authenticate('local') when registering a new user with passport-local-mongoose?

Following the The Complete 2023 Web Development Bootcamp-course by the App Brewery on Udemy, having progressed to lesson 386: Using Passport.js to Add Cookies and Sessions, I am wondering what the purpose is of (req, res, function() {...}) immediately after passport.authenticate('local') for registering a new user using passport-local-mongoose.
Source where the teacher has it from: https://mherman.org/blog/user-authentication-with-passport-dot-js/
(referenced in the documentation for passport-local-mongoose)
In context from the above link:
app.post('/register', function(req, res) {
Account.register(new Account({ username : req.body.username }), req.body.password, function(err, account) {
if (err) {
return res.render('register', { account : account });
}
passport.authenticate('local')(req, res, function () {
res.redirect('/');
});
});
});
Why isn't it written as:
...
passport.authenticate('local', function(req, res) {
res.redirect('/');
});
...
with the callback included as an argument?
Trying approaches that adhere to what I've become familiar with thus far, found in the Passport.js documentation and the passport-local-mongoose documentation, the user gets registered, but the redirection to the secrets-page is not done, instead having the page's load-indicator run continuously without changing from the register-page.
The route for reference below.
app.route("/register").get(function (req, res) {
res.render("register");
}).post(function (req, res) {
User.register({username: req.body.username}, req.body.password, function (err, user) {
if (err) {
console.log(err);
res.redirect("/register");
}
//WORKS: The App Brewery
//Based on: https://mherman.org/blog/user-authentication-with-passport-dot-js/#add-registerjade, 2022-12-25
passport.authenticate("local")(req, res, function () {
res.redirect("/secrets");
});
//DOESN'T WORK: Passport documentation on authentication
// passport.authenticate(
// "local",
// {failureRedirect: "/", failureMessage: true},
// function (req, res) {
// res.redirect("/secrets");
// });
//DOESN'T WORK: passport-local-mongoose documentation
// const authenticate = User.authenticate();
// authenticate(req.body.username, req.body.password, function (err, result) {
// if (err) {
// console.log(err);
// } else {
// res.redirect("/secrets");
// }
// });
});
});

How to pass Data Between multiple routes in express?

app.post("/login", passport.authenticate("local",), function (req, res) {
const user = new Model({
username: req.body.username,
password: req.body.password,
});
req.login(user, function (err) {
if (err) {
console.log("wrong password");
} else {
passport.authenticate("local")(req, res, function () {
res.redirect("/admin");
});
}
});
});
app.post("/admin", function (req, res) {
Model.findOne({username: "siddharth"}).exec(function(err, foundList){
if(foundList)
{
const list = new linkModel({
linkTitle: req.body.linkTitle,
linkUrl: req.body.linkUrl,
});
foundList.links.push(list);
foundList.save();
res.redirect("/admin");
}
else
{res.send("redirect to home page and then login");
res.redirect("/login");
}
});
});
How can i pass the username when authenticated from login routeto other route(admin) where mongoose query is defined findone?
As i have defined it explicitly.
Or i simple terms how can i pass the data among routes ?
You can't. Instead use a middleware to do the checks you want and pass on the result to another middleware or return the response in case of error.

Redirect Passport Login Based on MongoDB Find

I have the login route router.post('/login', authController.login). My controller uses passport and looks like:
exports.login = passport.authenticate('local', {
failureRedirect: '/login',
failureFlash: 'Failed Login',
successRedirect: '/',
successFlash: 'You are now logged in'
});
This works fine but I want to redirect to /store if the user doesn't has a device and /device if they do, based on the query:
const devices = await Device.find({ owner: req.user._id });
What is the best way to do this? I tried:
router.post('/login', authController.login, deviceController.hasDevice);
exports.login = (req, res, next) => {
passport.authenticate('local', {
failureRedirect: '/login',
failureFlash: 'Failed Login'
});
next();
};
exports.hasDevice = async (req, res) => {
const devices = await Device.find({ owner: req.user._id });
if (!devices.length) {
res.render('store', { title: 'Store' });
} else {
res.render('devices', { title: 'My Devices', devices });
}
};
but there is no user object on req when I get to hasDevice. I.e. I get "cannot find _id of undefined."
You can achieve that by using Custom Callback in passport.authenticate().
router.post('/login', async function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err || !user) {
return res.redirect('/login');
}
const devices = await Device.find({ owner: user._id });
if (!devices.length) {
res.render('store', { title: 'Store' });
} else {
res.render('devices', { title: 'My Devices', devices });
}
})(req, res, next);
});
What I was trying to do was solved simply by using redirects like:
router.get('/', someController.findRoute));
exports.findRoute= async (req, res) => {
const devices = await Device.find({ owner: req.user._id });
if (!devices.length) {
res.redirect('/store');
} else {
res.redirect('/devices');
}
};

Why is req.IsAuthenticated() return false even that req.session.passport.user has everything

Hi I have the following code. After I did req.login, req._passport has the right information there. However, after I call res.redirect("/profile"), inside my isAuthenticated function, req._passport is undefined, but req.session.passport.user has the right information. I looked at the req.isAuthentication method, it was looking for req._passport. Any reason why req._passport is undefined after redirect, and why there are both req._passport and req.session.passport? Thanks!
app.post('/signin', function (req, res, next) {
passport.authenticate('local-signin', function (err, user, info) {
......
req.login(user, function (err) {
console.log(req._passport); // Here req._passport is set.
return res.redirect('/profile');
});
});
})(req, res, next);
});
app.get('/profile', isAuthenticated, profile.index);
function isAuthenticated(req, res, next) {
console.log(req.session.passport.user); // looks good
console.log(req._passport) // undefined
if (req.isAuthenticated()) {
console.log("authenticated"); // Not reaching here
return next();
}
console.log("not authenticated"); // reaching here
res.redirect('/signin');
}

PassportJS rename "user" object

I am using PassportJS for my login functionalIs there a way to change the "user" object name in the request?
This is how it works now, by default (req.user):
function (req, res, next) {
if (!req.user) {
req.flash('error', 'Please sign in to access this page.');
res.redirect('/login');
} else {
next();
}
}
I would like to use the following instead (req.candidate):
function (req, res, next) {
if (!req.candidate) {
req.flash('error', 'Please sign in to access this page.');
res.redirect('/login');
} else {
next();
}
}
You can change it in initialization:
passport.initialize( {
userProperty: 'student' // defaults to 'user' if omitted
})
This code set: req.student
What you will do next depends on you and the used framework.
Look at source code:
Passport source code

Resources