Reputation: 5195
I don't understand why req.user
is undefined
after signup but it is not at login. I thought I did pretty much the same thing for login.
After I do signup I get the user in the db, then do json the req.user
and it returns null.
My end goal is to redirect to the /
route after signup. In the /
route I want to test to see if req.user is not null and give an appropriate message about if the user is authenticated or not .
const express = require("express");
const ejs = require("ejs")
const bodyParser = require("body-parser");
// const multer = require("multer");
const mongoose = require("mongoose");
const app = express();
const User = require("./database/models/user");
const port = process.env.port || 3000;
/**********Express session*********/
const expressSession = require("express-session");
/**********************************/
const passport = require("passport");
const localStrategy = require("passport-local").Strategy;
mongoose.connect("mongodb://localhost/passport-ajax");
//Make sure capital P for promise.
mongoose.Promise = global.Promise;
app.use(bodyParser.urlencoded({extended : true}));
app.use(bodyParser.json());
// app.use(multer({dest : "./uploads"}));
app.use(expressSession({
secret : "longString",
resave:false,
saveUninitialized: false
}))
/********************Configure passport*************************/
passport.use("login", new localStrategy({
usernameField : "emailOrUsername",
passwordField : "password",
passReqToCallback : true
},
function(req, username, password, done){
console.log("HIT HERE");
User.findOne({emailOrUsername: username})
.then((user)=>{
console.log("FINDING!!");
if(!user){
console.log("My error: NO SUCH USER");
return done(null, false, "No such user");
}
if(password !== user.password){
console.log(`Password Doesnt Match`);
done(null, false , "Passwords dont match");
}
console.log("USER MATCHED!!");
done(null, user)
})
.catch((err) => console.log(err));
}
))
passport.use("signUp", new localStrategy({
usernameField : "emailOrUsername",
passwordField : "password",
passReqToCallback : true
},
function(req, username, password, done){
// Removing from the DB first so there won't be multiple records while testing.
User.remove({})
.then(() =>{
User.findOne({emailOrUsername : username})
.then((user) => {
console.log("FINDING INSIDE SIGNUP");
if(user){
return done(null, false, "User "+ username + "allready exists. " );
}
var user = {
emailOrUsername : username,
password : password
};
new User(user).save()
//possible do done(err)
.then((newUser) =>{
if(!newUser) return done("Failed On Create User");
done(null, user)
})
})
})
.catch((err) => {
console.log(err);
})
}
))
function verifyAuth(req, res, next){
if(!req.isAuthenticated()){
return res.status(401).json({
err : "Please login correctly. You received a 401 error.",
sesstionId : req.session.id
})
}
next();
}
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function(user, done){
done(null, user.id);
});
passport.deserializeUser(function(id, done){
User.findById(id, function(err, user){
done(err,user);
})
})
/**************************************************************/
app.set("view engine", "ejs");
//file will be served like http://localhost:4000/style.css
app.use(express.static(__dirname + "/public"));
app.get("/", (req, res) => {
console.log("req.user : ", req.user);
console.log("session: ", req.session);
const authenticated = req.user ? true : false;
var query = req.query.message;
res.render("index", {
query,
authenticated
})
})
app.get("/signUp", (req, res) =>{
res.render("signUp", {
})
})
app.post("/signUp", (req, res, next) => {
// console.log(req.body);
passport.authenticate("signUp", function(err, user, info){
if(err) console.log(err, " authenticate Signup error! ");
if(!user) console.log("USER ERROR!");
req.login(user, function(err) {
if(err) return err;
console.log("req.login called!")
console.log("INFO, " , info)
})
// res.redirect("/");
res.status(201).json({
user : user,
session : req.session,
"req.user" : req.user // This is null right now.
});
})(req, res, next)
}, function(err, req, res, next){
console.log("req.isAuthenticated() >", req.isAuthenticated());
});
app.get("/login", (req,res) =>{
res.render("loginForm");
});
app.post("/login", function(req, res, next) {
console.log("req.body : ", req.body)
passport.authenticate("login", function(err, user, info){
console.log("inside authenticate");
if(err) console.log(err, " ", req.session.id);
if(!user) console.log("No user : ", info);
req.login(user, function(err) { // need this when using custom function
if(err) console.log(err);
});
res.status(201).json({
user : user,
session : req.session,
"req.user" : req.user
});
})(req, res, next); // very import to call this self-executing function
}, function(err, req, res, next){
//possible function here
});
app.get("/unProtected", (req, res) => {
res.json({
session : req.session,
"req.user" : req.user
})
})
app.get("/protected", verifyAuth, (req, res) =>{
res.json({
session : req.session,
"req.user" : req.user
});
});
app.listen(port, function(){
console.log(`Listening on port ${port}`);
})
Upvotes: 0
Views: 3223
Reputation: 81
I know its quite a late answer to your question. But right now when i was doing my project i came across the same problem. SO i would suggest you to have a local strategy of passport like this :
passport.use(new LocalStrategy(
function(username, password, done) {
console.log(username);
console.log(password);
db.collection('user-details').findOne({user_name:username},(err,result)=>{
if(err) {done(err)};
if(result.length == 0){
done(null,false);
}else{
const results = JSON.stringify(result);
var hash1 = JSON.parse(results);
var hash = hash1.password;
console.log( hash);
bcrypt.compare(password,hash,function(err,response){
if(response==true){
return done(null,{user_id:hash1._id});
}else{
return done(null,false);
}
});
}
});
}
));
and use this strategy in each post login and post register.In post register ; after storing the username and password to the database like this
app.post('register.html',(req,res,next)=>{
//store the username and password into the database
next();
});
Do remember to use next after the req,res object as it will transfer the control to the next middleware in the app; i.e. the middleware written just after this post method. And the middleware next to this will be passport's local strategy. Use it like this:
app.post('/register.html',passport.authenticate('local',{
successRedirect: '/website.html',
failureRedirect: '/register.html'
}));
Upvotes: 0
Reputation: 5345
req.login
acts asynchronously, that's why you pass it a callback function. So you should move every response inside this callback this way you give it enough time to doing it's configuration:
req.login(user, function(err) {
if (err) return err;
console.log("req.login called!");
console.log("INFO, ", info);
return res.status(201).json({
user: user,
session: req.session,
"req.user": req.user
});
});
Also in passport.use("signUp"...
you should call the callback with newUser:
var newUser = new User(user);
newUser.save(function(err) {
if (err) throw err;
done(null, newUser);
});
And also serialize your user with _id
instead of id
:
passpost.serializeUser(function(user, done) {
done(null, user._id);
});
Upvotes: 1