Related
I have been trying to solve this ise quite a few days and decided to get community help here.
I have been following the tutorial and here is the problem I face. When I try to get the value of req.user.Firstname in the below code, it threw an error of TypeError: Cannot read properties of undefined (reading 'name'). I am not sure what is going wrong here exactly. Below are the codes from my index.js,app.js file,User.js.
Note: I still render the dashboard page but without the firstName value.
App.js file
const path = require("path");
const express = require("express");
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const morgan = require("morgan");
const exphbs = require("express-handlebars");
const connectDB = require("./config/db");
const passport = require("passport");
const session = require("express-session");
const MongoStore = require("connect-mongo");
const routes = require("./routes/index");
const authent = require("./routes/auth");
const bodyParser = require("body-parser");
const cookieSession = require("cookie-session");
//Loading the config
dotenv.config({ path: "./config/config.env" });
//Passport config
require("./config/passport")(passport);
//Coonecting to DB
connectDB();
const app = express();
app.use(express.json());
// Body parser
app.use(express.urlencoded({ extended: false }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
//Morgan
if (process.env.NODE_ENV === "development") {
app.use(morgan("dev"));
}
//Handlebars
app.engine(".hbs", exphbs.engine({ defaultLayout: "main", extname: ".hbs" }));
app.set("view engine", ".hbs");
//Session middleware
app.use(
session({
secret: "the secret",
resave: false,
saveUninitialized: false,
// cookie: { secure: true },
store: MongoStore.create({ mongoUrl: process.env.MONGO_URI }),
})
);
//Passport middleware
app.use(passport.initialize());
app.use(passport.session());
//Static folder
app.use(express.static(path.join(__dirname, "public")));
//Routes
app.use("/", routes);
app.use("/auth", authent);
const PORT = process.env.PORT || 3000;
app.listen(
PORT,
console.log(
`The server is running IN ${process.env.NODE_ENV} mode, on port ${PORT}`
)
);
Index.js
const express = require("express");
const router = express.Router();
const { ensureAuth, ensureGuest } = require("../middleware/auth");
//Description Login/Landing page
//#route GET /
router.get("/", ensureGuest, function (req, res) {
res.render("login", {
layout: "login",
});
});
//Description Dashboard page
//#route GET /dashboard
router.get("/dashboard", ensureAuth, function (req, res) {
res.render("dashboard", {
name: req.user.firstName,
});
});
module.exports = router;
User model
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
googleId: {
type: String,
// required: true,
},
displayName: {
type: String,
required: true,
},
firstName: {
type: String,
required: true,
},
familyName: {
type: String,
required: true,
},
image: {
type: String,
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("User", UserSchema);
Passport.js
const GoogleStrategy = require("passport-google-oauth20").Strategy;
const mongoose = require("mongoose");
const User = require("../models/User");
require("https").globalAgent.options.rejectUnauthorized = false;
module.exports = function (passport) {
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/callback",
},
async (accessToken, refreshToken, profile, done) => {
console.log(profile);
const newUser = {
googleId: profile.id,
displayName: profile.displayName,
firstName: profile.name.givenName,
familyName: profile.name.familyName,
image: profile.photos[0].value,
};
try {
let user = await User.findOne({ googleId: profile.id });
if (user) {
done(null, user);
} else {
user = await User.create(newUser);
done(null, newUser);
}
} catch (error) {
console.log(error);
}
}
)
);
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (user, done) {
User.findById(user.id, function (error, user) {
done(error, user);
});
});
};
Any ideas what I might have been doing wrong here? Thanks!
I've been stuck on this for two days. I got it working last night, and this morning I updated some stuff and removed some unnecessary code, which ended up not working. The error persists on the passport serialization, "TypeError: Cannot set properties of undefined (setting 'user')"
app.js
const mongoose = require("mongoose"); //Mongo driver
var session = require('express-session');
const passport = require('passport');
const MongoStore = require('connect-mongo');
var express = require("express");
const bodyParser = require('body-parser'); //For parsing post requests
//Route files
const mainRoutes = require("./routes/main");
const authRoutes = require("./routes/auth");
require("./passport")(passport);
//Express setup
var app = express();
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
mongoose
.connect
....
//Express Session
app.use(session({
resave: true,
saveUninitialized: false,
secret: 'SECRET',
store: new MongoStore({ mongoUrl: process.env.MONGO_URI, ttl: 12 * 60 * 60 * 1000 })
}));
//Passport Middleware
app.use(passport.initialize());
app.use(passport.session());
app.use(mainRoutes);
app.use(authRoutes);
passport.js
const bcrypt = require("bcrypt");
const localStrategy = require("passport-local").Strategy;
const FacebookStrategy = require("passport-facebook").Strategy;
... Twitter, Google ..
const Users = require("./models/userModel");
module.exports = function (passport) {
passport.serializeUser(function(user, done){
done(null, user._id);
});
passport.deserializeUser(function(id, done){
Users.findById(id, function(err, user){
done(err, user);
});
});
//..Not including local or the other strategies as they all lead to the same thing
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/callback",
// passReqToCallback : true, //Tried with both these two commented lines
// profileFields: ['id', 'emails']
},
function (req, accessToken, refreshToken, profile, done) {
console.log(profile);
Users.findOrCreate({ "platform.id": profile.id, "platform.name": profile.provider, "email": profile.emails[0].value }, function (err, user) {
console.log(user);
return done(null, user);
});
}));
};
routes/auth.js
const passport = require('passport');
const router = require("express").Router();
...
router.get('/auth/facebook', passport.authenticate('facebook'));
router.get('/auth/facebook/callback', passport.authenticate('facebook', {
successRedirect : '/',
failureRedirect: '/' })
);
...
userModel.js
const mongoose = require("mongoose");
const findOrCreate = require('mongoose-findorcreate');
const {usernameGen} = require("../utils/functions");
const userSchema = new mongoose.Schema({
platform: {
name: String,
id: String
},
email: {
type: String
},
username: {
type: String,
min: 4,
max: 20,
default: usernameGen
},
password: {
type: String,
min: 6
},
isAvatarImageSet: {
type: Boolean,
default: false
},
avatarImage: {
type: String,
default: ""
},
authLevel: {
type: String,
enum: ["admin", "moderator", "member", "anon"],
default: "anon"
},
});
userSchema.plugin(findOrCreate);
module.exports = mongoose.model("Users", userSchema);
Sorry for dumping out most of the stuff here, but passportjs's documentation has been driving me crazy. Found similar issues from other people, but the solutions were to downgrade passportJS to a REALLY older version, or wrong stuff initializing at the wrong place, or just wrongly serializing the user.
Console logging the user going into passport.serializeUser(), reveals all the user data correctly along with the user's _id.
Any help would be greatly appreciated, and thanks for checking my issue out!
I get an error TypeError: Cannot read property 'register' of undefined while attempting to register any user to the database using a post request via postman on route http:localhost:3000/signup, I searched for similar errors and tried the following:
1- installing and using bodyparser and using it on server.js
2- declaring express session before passport initialization and declaration of passport.session
and i use body to pass json data to the route on postman enter image description here
/backend/routes/signup.js
const router = require("express").Router();
const passport = require("passport");
const User = require("../models/users").default;
router.route("/signup").get((req, res) => {
res.render("/signup");
});
router.route("/signup").post((req, res) => {
const registeredUser = {
firstName: req.body.firstName,
lastName: req.body.lastName,
username: req.body.username,
email: req.body.email
}
User.register(registeredUser, req.body.password, function(err, user) {
if (err) {
console.log(err);
} else {
passport.authenticate("local")(req, res, function() {
res.json("User registered");
res.redirect("/notes/:username");
// redirect user or do whatever you want
});
}
// Value 'result' is set to false. The user could not be authenticated since the user is not active
});
});
// const newUser = new User({
// firstName,
// lastName,
// username,
// email,
// password
// });
// newUser.save()
// .then(() => res.json("User " + username + " is registered to database!"))
// .catch(err => res.status(400).json("Error" + err
module.exports = router;
/backend/server.js
//jshint esversion:6
const express = require("express");
const cors = require("cors");
const bodyParser = require('body-parser');
const mongoose = require("mongoose");
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const User = require("./models/users");
const Note = require("./models/notes");
const notesRouter = require("./routes/notes");
const registerRouter = require("./routes/signup");
const loginRouter = require("./routes/signin");
require('dotenv').config();
const app = express();
const port = process.env.PORT || 3000;
app.use(cors());
app.use(express.json());
app.set('view engine', 'ejs');
app.use( bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(require("express-session")({
secret:"This is keeper clone",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true});
mongoose.set("useCreateIndex", true);
const connection = mongoose.connection;
connection.once("open", () => {
console.log("MongoDb database connection established successfully");
});
app.use("/", notesRouter);
app.use("/", registerRouter);
app.use("/", loginRouter);
app.listen(port, () => {
console.log("Server is running on port 3000!");
});
/backend/models/users.js
const mongoose = require("mongoose");
const passportLocalMongoose = require("passport-local-mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3
},
email: {
type: String,
required: true,
unique: true,
trim: true,
},
password: {
type: String,
required: true,
minlength: 8
},
googleId: {
type: String
}
},
{
timestamps: true,
});
userSchema.plugin(passportLocalMongoose);
const User = mongoose.model("User", userSchema);
module.exports = User;
I have previously used the same approach in another project and it worked fine for me
//jshint esversion:6
require('dotenv').config();
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const session = require('express-session');
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const FacebookStrategy = require("passport-facebook").Strategy;
const findOrCreate = require('mongoose-findorcreate');
const app = express();
app.use(express.static("public"));
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(session({
secret: "Our little secret.",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect("mongodb://localhost:27017/userDB", {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set("useCreateIndex", true);
const userSchema = new mongoose.Schema ({
email: String,
password: String,
googleId: String,
facebookId: String,
secret: String
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
const User = new mongoose.model("User", userSchema);
passport.use(User.createStrategy());
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use(new GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/secrets",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
console.log(profile);
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
passport.use(new FacebookStrategy({
clientID: process.env.APP_ID,
clientSecret: process.env.APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/secrets"
},
function(accessToken, refreshToken, profile, done) {
User.findOrCreate({ facebookId: profile.id }, function(err, user) {
if (err) { return done(err); }
done(null, user);
});
}
));
app.get("/", function(req, res){
res.render("home");
});
app.get("/auth/google",
passport.authenticate('google', { scope: ["profile"] })
);
app.get("/auth/google/secrets",
passport.authenticate('google', { failureRedirect: "/login" }),
function(req, res) {
// Successful authentication, redirect to secrets.
res.redirect("/secrets");
});
app.get('/auth/facebook', passport.authenticate('facebook'));
app.get('/auth/facebook/secrets',
passport.authenticate('facebook', { successRedirect: '/secrets',
failureRedirect: '/login' }));
app.get("/login", function(req, res){
res.render("login");
});
app.get("/register", function(req, res){
res.render("register");
});
app.get("/secrets", function(req, res){
User.find({"secret": {$ne: null}}, function(err, foundUsers){
if (err){
console.log(err);
} else {
if (foundUsers) {
res.render("secrets", {usersWithSecrets: foundUsers});
}
}
});
});
app.get("/submit", function(req, res){
if (req.isAuthenticated()){
res.render("submit");
} else {
res.redirect("/login");
}
});
app.post("/submit", function(req, res){
const submittedSecret = req.body.secret;
//Once the user is authenticated and their session gets saved, their user details are saved to req.user.
// console.log(req.user.id);
User.findById(req.user.id, function(err, foundUser){
if (err) {
console.log(err);
} else {
if (foundUser) {
foundUser.secret = submittedSecret;
foundUser.save(function(){
res.redirect("/secrets");
});
}
}
});
});
app.get("/logout", function(req, res){
req.logout();
res.redirect("/");
});
app.post("/register", function(req, res){
User.register({username: req.body.username}, req.body.password, function(err, user){
if (err) {
console.log(err);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, function(){
res.redirect("/secrets");
});
}
});
});
app.post("/login", function(req, res){
const user = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, function(err){
if (err) {
console.log(err);
} else {
passport.authenticate("local")(req, res, function(){
res.redirect("/secrets");
});
}
});
});
app.listen(3000, function() {
console.log("Server started on port 3000.");
});
you use register function of User Model
User.register(registeredUser, req.body.password, function(err, user)
but you don't defined it, for defined register method in mongoose, you can use this documentation or use static method in mognoose
I have solved it by just removing .default from the User import statement in route file
const User = require("../models/users").default;
const User = require("../models/users");
I understand that this question has been asked on here before, but the answers on those questions haven't helped me at all.
After the successful authentication of my user through passport with the "#oauth-everything/passport-discord" strategy, req.user is still undefined.
Here is the code in my main file,
// Modules
const compression = require("compression"),
cookieParser = require("cookie-parser"),
cors = require("cors"),
express = require("express"),
exphbs = require("express-handlebars"),
session = require("express-session"),
logger = require("morgan"),
path = require("path"),
createError = require("http-errors"),
mongoose = require("mongoose"),
debug = require("debug"),
flash = require("connect-flash"),
passport = require("passport");
// Local files
const setupPassport = require("./src/setupPassport");
// Passport
setupPassport(passport);
// Mongoose
mongoose.connect("mongodb://localhost/website", {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
debug("sb:mongoose")("Successfully connected to mongodb.");
}).catch(e => {
debug("sb:mongoose")("Unable to connect to mongodb\n" + e);
});
// Routers
const indexRouter = require("./routes/index");
const loginRouter = require("./routes/login");
// App setup
const app = express();
app.set("views", path.join(__dirname, "views/pages"));
// View engine
app.engine("hbs", exphbs({
defaultLayout: "user",
layoutsDir: "./views/layouts/",
partialsDir: "./views/parials/",
extname: "hbs"
}));
app.set("view engine", "hbs");
// Middleware
app.use(logger("dev"));
app.use(compression());
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use(session({
secret: "replace with env secret",
resave: false,
saveUninitialized: true,
cookie: {secure: true}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(cors());
app.use(flash());
this is my setup passport file
const pprt = require("passport");
const { Strategy, Scope } = require("#oauth-everything/passport-discord");
const User = require("../models/user");
/**
* #param {pprt} passport
*/
module.exports = (passport) => {
passport.serializeUser((user, done) => {
return done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
User.findById(id, (err, res) => {
if (err) return done(err);
return done(null, res);
});
});
passport.use(new Strategy(
{
clientID: "no",
clientSecret: "no way",
callbackURL: "http://localhost:3000/login/auth/callback",
scope: [Scope.EMAIL, Scope.IDENTIFY]
},
(accessToken, refreshToken, profile, cb) => {
User.findOne({user_id: profile.id}, (err, res) => {
if (err) return cb(err);
if (!res) {
let newUser = new User({
user_id: profile.id,
username: profile.username,
displayName: profile.displayName,
email: profile.emails[0].value,
verified: profile.emails[0].verified,
tokens: {
access: accessToken,
refresh: refreshToken
}
});
newUser.save().then(user => {
cb(null, user);
});
} else {
res.updateOne({
user_id: profile.id,
username: profile.username,
displayName: profile.displayName,
email: profile.emails[0].value,
verified: profile.emails[0].verified,
tokens: {
access: accessToken,
refresh: refreshToken
}
}, (err, user) => {
if (err) return cb(err);
cb(null, user);
});
}
});
}
));
};
as i said req.user still returns undefined even after successful authentication does anyone have any idea why?
I should also mention that the user object is saved to mongodb perfectly which is why this perplexes me so much.
This is my first time doing user authentication and I think I'm nearly complete. I'm using Express with Passport.js and MongoDB/Mongoose. When I run my gulp file everything loads correctly but when I attempt to login with my credentials I'm constantly redirected to the failure page (home screen). Here's my code:
// Initialize
const bodyParser = require('body-parser')
const path = require('path')
const bcrypt = require('bcryptjs')
const express = require('express')
const session = require('express-session')
const cookieParser = require('cookie-parser')
const passport = require('passport'),
LocalStrategy = require('passport-local').Strategy
let userData = require('./models/user.js')
const app = express()
// Configuration
app.use(cookieParser())
app.use(session({ secret: 'ThisIsTheSessionSecret', resave: true, saveUninitialized: true }))
app.use(passport.initialize())
app.use(passport.session())
app.use(express.static(path.join(__dirname, '../../docs')))
app.use(express.static(path.join(__dirname, '../../src')))
app.set('port', process.env.PORT || 8080);
app.set('view engine', 'pug')
app.set('views', 'src/pages')
let urlencodedParser = bodyParser.urlencoded({ extended: false })
// Configure authentication and sessions
passport.use(new LocalStrategy(
function(username, password, done) {
user.findOne({ username: username }, function(err, user) {
if (err) { console.log(err) }
if (!user) {
return done(null, false, { message: 'Incorrect username.' })
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' })
}
return done(null, user)
})
}
));
// 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.listen(app.get('port'))
console.log('Listening on port: ' + app.get('port'))
// Initialize database (local or remote?)
const MongoClient = require('mongodb').MongoClient,
mongoose = require('mongoose'),
assert = require('assert')
const database = 'mongodb://localhost:27017/database'
mongoose.connect(database)
let db = mongoose.connection
db.on('error', console.error.bind(console, 'connection error'))
db.once('open', function() {
// let testUser = new userData.UserModel({ username: 'PodcatchUser', password: 'RIPHarambe' })
// console.log(testUser.username)
})
// Routing
app.get('/', function(req, res) {
console.log('Welcome!')
res.render('index')
})
// Registration
app.post('/signup', urlencodedParser, function(req, res) {
let username = req.body.username,
password = req.body.password,
salt = bcrypt.genSaltSync(10),
hash = bcrypt.hashSync(password, salt)
let user = new userData.UserModel({
username: username,
password: hash
})
console.log(user.username)
console.log(user.password)
user.save(function(err) {
if (err) {
return console.log(err, user)
} else {
console.log('User has been saved to the database successfully')
}
})
res.end()
})
// Login
app.post('/login', passport.authenticate('local', { successRedirect: '/success',
failureRedirect: '/' }), function(req, res) {
res.end()
})
and the code in the userData module:
const mongoose = require('mongoose')
let UserSchema = mongoose.Schema({
username: String,
password: String
})
let UserModel = mongoose.model('UserModel', UserSchema)
module.exports.UserSchema = UserSchema
module.exports.UserModel = UserModel
I'm really confused as to what's happening. Mongo saves the credentials and hashed password to the database, I create a session and have a cookie parser but it doesn't authenticate. Help would be greatly appreciated :)