req.user and Is Authenticated always false - javascript

I am using react with express.js (inside router/user.js)
router.get("/", function (req, res) {
console.log("this is u" , req.user)
console.log(req.isAuthenticated());
if (req.user) {
res.json({ user: req.user })
} else {
res.json({ user: 'does not exsist' })
}
});
Here the console.log show the value against them as always undefined
console.log("this is u" , req.user)
console.log(req.isAuthenticated());
The above code always console.log false, Now I went through the other examples where they mentioned the problem can be due to the way you put things in server.js(or app.js) and hence I checked and think that my problem is not because of that reason, Anyway this is how I am adding stuff
app.use(session({
secret: 'keyboard cat', // -> used to encode and decode the session, the seceret we used will be used to encode to decode
resave: true,
saveUninitialized: true,
}));
app.use(passport.initialize());
app.use(passport.session());
//Session
passport.use(new LocalStrategy(user.authenticate()));
passport.serializeUser(user.serializeUser());
passport.deserializeUser(user.deserializeUser());
Here is my complete proper repository if someone wants to view: https://github.com/irohitb/litifier-
Now, Can anyone please guide me about fixing this problem?

This is because the login process is not being executed.
This results into cookie not being sent, which results into cookie not being read in the next request, which results into req.isAuthenticated() returning false
From the passport.js docs,
Note that when using a custom callback, it becomes the application's
responsibility to establish a session (by calling req.login()) and
send a response.
Solution:
As this looks like your signup page, I dont think you need to do passport.authenticate here. That is for login. Remove that.
After you register the new user, do the following:
req.logIn(user, function (err) {
if (err) {
return next(err);
}
return res.json(user) // send whatever you want or redirect
});

Try adding {credentials: 'include'} in the route
Example
get('/test', {credentials: 'include'})

Related

Trouble authenticating with passport after refactoring code

I am building out a RESTful app using node.js, mongoose, express & passport using .ejs as a front end. I'm trying to add authentication back in with passport. With the current code I can register a new user, but that new user does not remain logged in, and after creating the user, I cannot login to do activities requiring authorization. There is no persistent user it seems. I'm using express-session as well.
I've searched for similar issues but any "fixes" have not seemed to help. I have nearly identical code in a similar app with the same stack...the main difference being the names of the resources (ie races instead of projects for example)
This will be the 3rd application I've used passport with, so it's not 100% new and with similar / same code, it has worked on my local installation. in this case, it was working fine including showing and hiding the login/logout buttons in my .ejs file.
Then I refactored the routes and now I cannot get passport to work at all.
I have compared code, placed the auth routes back into the app.js file, tried to console.log the req.user with and without logging in and it just won't work anymore...none of the passport routes seem to function.
I've reinstalled the node modules from my package.json file, copied & pasted the passport setup from previously working files, and the req.user is always undefined, and I'm unable to register a new user.
I've essentially reinstalled all of the passport stuff, short of deleting the auth file and app.js lines and restarting...but I should be able to trouble shoot this without deleting content.
Sadly I did not save a version prior to refactoring. :(
Any suggestions on why this may have occurred AFTER I refactored the routes files when it was working well just prior? As far as I can tell I have reconstructed things as they were prior to refactoring.
Here is my app.js passport setup
//setup passport
app.use(require("express-session")({
secret: "Fig is the best puppy ever",
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(function(req, res, next){
console.log("Current User: " + req.user)
res.locals.currentUser = req.user;
next();
});
and my auth routes:
//Authentication Routes
//show signup form
app.get('/register', function(req,res){
res.render("register")
})
//user signup
app.post("/register", function(req,res){
//res.send("Signing you up")
console.log(req.body)
var newUser = new User({username: req.body.username})
User.register(newUser, req.body.password, function(err, user){
if(err) {
console.log(err);
return res.render('register')
} else {
passport.authenticate("local")(req,res, function(){
console.log("Created new user")
res.redirect("/projects")
})
}
})
})
//LOGIN ROUTES
//render login form
app.get("/login", function(req,res){
res.render("login")
})
app.post("/login", passport.authenticate("local",
{
successRedirect: "/projects",
failureRedirect: "/login"
}), function(req,res) {
// console.log("Logged in" +currentUser)
// res.redirect("/projects")
})
//Logout Routes
app.get("/logout", function(req,res) {
req.logout()
res.redirect("/projects")
})
It looks like you're missing the req.login call on authenticate. Try adding this to your else in your register middleware.
passport.authenticate("local")(req, res, function() {
req.login(user, function(err) {
if (err) {
console.log(err);
res.redirect('/register');
} else {
res.redirect('/projects')
}
})
})
Solution by OP.
Solved by reordering my route requirements and the passport set up. The correct sequence is below.
//setup passport
app.use(require("express-session")({
secret: "Fig is the best puppy ever",
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
//I MOVED THESE LINES TO BELOW THE PASSPORT SETUP
// Route setup
app.use("/users", userRoutes)
app.use(authRoutes)

Checking if a user is logged in with PassportJS / ExpressJS

I have an Angular app built on the MEAN stack, using Passport to log in and authenticate users. I'm a little confused about how authentication works.
I have a route that Angular passes an $http call to to check if a user is logged in (and can thus access certain pages). The route looks like this:
// route to test if the user is logged in or not
app.get('/loggedin', function(req, res) {
res.send(req.isAuthenticated() ? req.user : '0');
});
From what I've read (which is very little, I can't find isAuthenticated() anywhere in the Passport docs...), Passport should be creating a persistent session for my users.
This works for the most-part, but if I close my Chrome application / reset my computer I have to log in again. I assumed that using Passport would mean that I don't need to create a hashed cookie to store login information. Is this not the case?
Other potential cause: I'm in development at the moment and am restarting the server often. Will the Passport sessions not persist through a server restart?
Edit: Here is my session config in app.js:
var session = require('express-session');
app.use(session({ secret: 'heregoesasupersecretsecret' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
If you are using passport for authentication in Node.js, you can use a middleware to check the authentication. I use the below code for this.
passport.use(new LocalStrategy({passReqToCallback : true}, function(req, username, password, done) {
models.Accounts.findOne({ where: { username: username}}).then(function(user) {
if (!user) {
console.log('Unkown User');
return done(null, false, {message: 'Unknown User'});
}
bcrypt.compare(password, user.password, function(err, isMatch) {
if (err) throw err;
if (isMatch) {
req.session.username = req.body.username;
return done(null, user);
} else {
return done(null, false, {message: 'Invalid Password'});
}
});
}).catch(function(err) {
return done(null, false);
});
}));
You can use express-session library in Node.js to handle user sessions. You can add a middleware in your code like below.
app.use(session({
secret: 'track_courier_application_secret_key',
cookie: {
maxAge: 300000
},
saveUninitialized: true,
resave: true
}));
In the above code I'm setting maxAge to 300K milli seconds. That is 5 minutes. After this a session object will be attached in every request to the server. You can access this session object using
req.session
Now you can write a get request like below to check if a user is logged in or not.
app.get('/accounts/isloggedin', function(req, res) {
if(req.session.username)
res.status(200).send('Hurray!');
else
res.status(401).send('User not logged in.');
});
You need to use a proper session store to put the sessions in to persist them between requests. Since you're using MongoDB, you could use connect-mongo.
Then you could do something like:
var session = require('express-session'),
MongoStore = require('connect-mongo')(session);
app.use(session({
secret: 'heregoesasupersecretsecret',
store: new MongoStore()
}
));
app.use(passport.initialize());
app.use(passport.session());

passport local mongoose req.user undefined

I'm currently encountering the following problem during implementation of passport js with the passport local mongoose plugin. Account creation and logging in is working correctly. However, after I have logged in passport never identifies me as a user that is logged in.
I have used the following pieces of code:
In my user model:
User.plugin(passportLocalMongoose);
In app.js (this order of inclusion is correct?):
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('keyboard cat'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({ secret: 'keyboard cat' }));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
In my routes:
router.post('/login', passport.authenticate('local'), function(req, res) {
res.json({ loggedIn: true });
});
which returns true, but the following keeps returning false (after logging in):
req.isAuthenticated()
Can anyone enlighten me what the cause may be?
Thanks!
You probably want to try an Express middelware, as was suggested in the comments.
For example:
function isAuthenticated(req, res, next) {
if(req.isAuthenticated()) {
return next()
} else {
// redirect users to login page
}
}
app.get('/anypage', isAuthenticated, function(req, res) {
// some reoute logic
})
From the looks of it, your order is fine. The most important part of the order is to have passport.initialize() and passport.session() come after your express-session configuration.
As for the issue with the initial authentication working, but subsequent requests showing an unauthenticated user, the issue could very well be because of cookies. I have run into a similar issue before, and the problem was in the way the HTTP requests were being made from the client.
If you are using the ES6 fetch API, then you will want to make sure to pass in an key credentials to the options object with a value of "include".
For example:
fetch('/restricted', {
method: 'get',
credentials: 'include'
});
The fetch API will not send credentials in cookies unless you specify it to. Hope this helps.
Additional resources: https://developers.google.com/web/updates/2015/03/introduction-to-fetch

Staying authenticated after the page is refreshed using Passportjs

I am building a SPA using express, mongoose and passportjs.
I have created a simple schema for my user:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
var User = new Schema({
username: String,
password: String,
first_name: String
}, { collection: 'users' });
User.plugin(passportLocalMongoose);
mongoose.model('User', User);
Configured passport using the User object which mongoose gave me:
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
And configured my app to authenticate the user when navigating to this route:
app.post('/login', passport.authenticate('local'), function(req, res, next) {
if (req.isAuthenticated()) {
return res.json({ state: 'success', user: { first_name: req.user.first_name } });
}
return res.json({ state: 'failure', message: 'cannot authenticate' });
});
Now I am able to successfully authenticate a user. And the browser saves a session id cookie.
My problem is that every time the user refreshes the page passport won't deserialize the user using the session id, what makes the user unauthenticated.
While accessing the req.user object in the site's root I get undefined what make me realize passport doesn't deserialize the user properly:
app.use('/', function (req, res, next) {
console.log(req.user); // prints undefined.
next();
});
What is the proper way for restoring a user after refreshing the page?
The solution is to store the sessions in the DB. I used connect-mongo.
app.js:
var mongoose = require('mongoose');
var expressSession = require('express-session');
var MongoStore = require('connect-mongo')(expressSession);
mongoose.connect(db_url, function (err) {
if (err) {
console.log(err);
}
});
app.use(expressSession({
secret: process.env.SESSION_SECRET || 'keyboard cat',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
after this, req.isAuthenticated() returns true on every request even after refreshing the page. (Thanks to app.use(passport.session()) which comes before any route handler)
app.use('/', function (req, res, next) {
if (req.isAuthenticated()) {
// returns true if a user already logged in.
}
next();
});
Looking at your post i can guess where problem is happening. In question you have pasted your back end expressjs code, but the problem is happening in the front end.
Think of a situation when you are working on normal javascript files, you make some edit in the variable values using Chrome dev tools of firebug n all. Let's say you refresh the page, do you still see the same edited value in the view? No right. Same is the case with your view, you are temporary holding user data. Although your backend is holding the values in req.user but your front end loses it when you refresh.
So you have to do either of below two :
Store your value in cookie on successful login and erase it when
logged out. So that cookie is never going to loose data even if you
refresh the page. Access the user data from that cookie whenever you need it
Call the backend API which returns value of req.user on your every
page refresh
I am not sure what frontend framework you are using for SPA, if you are using AngularJS then you can make use of cookieStore service it does the job beautifully.

Passport JS "Can't set headers after they are sent"

Getting this error when I successfully log in with passport JS. Trying to redirect to the home page once I log in.
Code that does it:
app.post('/login',
passport.authenticate('local', {failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
Full Error:
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:644:11)
Am I missing something? Not sure why this error is happening. I'm still able to use the app, I just dont want the error.
You are redirecting the user so serializeUser function is being called twice. And in
passport.use(new FacebookStrategy({
...
be sure to add this else or it gets called twice, thus sending the headers twice and causing error. Try this:
passport.use(new FacebookStrategy({
...
},
function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
// To keep the example simple, the user's Facebook profile is returned to
// represent the logged-in user. In a typical application, you would want
// to associate the Facebook account with a user record in your database,
// and return that user instead.
User.findByFacebookId({facebookId: profile.id}, function(err, user) {
if (err) { return done(err); }
if (!user) {
//create user User.create...
return done(null, createdUser);
} else { //add this else
return done(null, user);
}
});
});
}
));
According to the PassportJS guide, you're supposed to let their middleware do all of the redirects.
app.post('/login', passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' }));
My guess is that the middleware is calling Express' res.redirect method just like you are in your example above, but has an error in its implementation (calling next when it shouldn't) and then your method is trying to call res.redirect again, and that causes the error to be thrown because you can only send a response to the client once in the HTTP protocol.

Categories

Resources