Related
I try to connect my Login page with mongoose. Unfortunetly it doesn`t work.
I get the error:
ObjectParameterError: Parameter "filter" to findOne() must be an object, got 637798b57bfa9d5fbede9c30
I tried to find the solution the whole day, but I cant figure it out. Im also still learning coding and struggle to understand everything of it, but most I understand.
if(process.env.NODE_ENV !== "production") {
require("dotenv").config()
}
const express = require('express')
const app = express()
const bcrypt = require('bcrypt')
const passport = require("passport")
const initializePassport = require("./passport-config")
const flash = require("express-flash")
const session = require("express-session")
const methodOverride = require("method-override")
const mongoose = require("mongoose")
const User = require("./user")
const uri = 'abc'
async function connect(){
try{
await mongoose.connect(uri)
console.log("connected")
} catch (error){
console.error(error)
}
}
connect();
const user = User
initializePassport(
passport,
email => User.find(user => user.email === email),
_id => User.find(user => user._id === _id)
)
app.set('view-engine', 'ejs')
app.use(express.urlencoded({extended: false}))
app.use(flash())
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false, // We wont resave the session var if nothing is changed
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride("_method"))
function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, password, done) => {
const user = await User.findOne({email:email});
console.log(user);
if (user == null) {
return done(null, false, { message: 'No user with that email' })
}
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user)
} else {
return done(null, false, { message: 'Password incorrect' })
}
} catch (e) {
return done(e)
}
}
passport.use(new LocalStrategy({ usernameField: 'email' }, authenticateUser))
passport.serializeUser((user, done) => done(null, user.id))
passport.deserializeUser((id, done) => {
return done(null, getUserById(id))
})
}
module.exports = initialize
app.get('/', checkAuthenicated, (req, res)=> {
res.render('index.ejs', {name: req.body.name})
})
app.get('/login', checkNotAuthenicated, (req, res)=> {
res.render('login.ejs')
})
app.post("/login", checkNotAuthenicated, passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login",
failureFlash: true
}))
app.get('/register', checkNotAuthenicated, (req, res)=> {
res.render('register.ejs')
})
app.post("/register", checkNotAuthenicated, async (req, res) => {
try {
const hashedPassword = await bcrypt.hash(req.body.password, 10)
//users.push({
const user = new User({
id: Date.now().toString(),
username: req.body.name,
email: req.body.email,
password: hashedPassword
})
user.save().then(()=> console.log("User saved"))
console.log(user)
res.redirect("/login")
} catch (e){
console.log(e);
res.redirect("/register")
}
})
app.delete("/logout", (req, res) =>{
req.logOut(
res.redirect("/login")
)
})
function checkAuthenicated(req, res, next){
if (req.isAuthenticated()){
return next()
}
res.redirect("/login")
}
function checkNotAuthenicated(req, res, next){
if (req.isAuthenticated()){
return res.redirect("/")
}
next()
}
app.listen(3000)
const bcrypt = require('bcrypt')
const mongoose = require("mongoose")
const userShema = new mongoose.Schema({
id: String,
username: String,
email: String,
password: String
})
module.exports = mongoose.model("User", userShema)
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')
const User = require("./user")
function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, password, done) => {
const user = await User.findOne({email:email});
console.log(user);
if (user == null) {
return done(null, false, { message: 'No user with that email' })
}
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user)
} else {
return done(null, false, { message: 'Password incorrect' })
}
} catch (e) {
return done(e)
}
}
passport.use(new LocalStrategy({ usernameField: 'email' }, authenticateUser))
passport.serializeUser((User, done) => done(null, User._id))
passport.deserializeUser(function(_id, done) {
User.findOne(_id, function (err, User) {
done(err, User);
});
});
}
module.exports = initialize
I think the problem lies somewhere in here:
passport.use(new LocalStrategy({ usernameField: 'email' }, authenticateUser))
passport.serializeUser((User, done) => done(null, User._id))
passport.deserializeUser(function(_id, done) {
User.findOne(_id, function (err, User) {
done(err, User);
});
});
But I`m not sure...
Thanks very much for your help.
You are mixing findOne and findById
findById does not need an object but the _id. As the docs (and also the method name) explain, under the hook it find by the id, so is like to do findOne({_id: id}).
From the docs:
findById(id) is almost* equivalent to findOne({ _id: id })
So the problem is you are trying to use simply the _id when the method expect an object to match the filter.
So you can use User.findOne({_id: _id}) or User.findById(_id)
As a beginner I was following a tutorial to make my first website with node.js but when I try to test a login with 100% valid information I get the following error:
Error: Failed to serialize user into session
Something weird I found is that when the error pops up I go back to the previous page, in this case the login page, and a welcome message I added on /profile.hbs/ pops up as if I was in a session.
This is my passport.js
const res = require('express/lib/response');
const passport = require('passport');
const pool = require('../database');
const router = require('../routes/usuario');
const LocalStrategy = require('passport-local').Strategy;
//const helpers = require('../lib/helpers')
passport.use('local.signin', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
}, async (req, username, password, done) => {
const rows = await pool.query('SELECT * FROM userr WHERE username = ?', [username])
if (rows.length > 0) {
const user = rows[0];
const validPassword = user.password == password
if (validPassword) {
done(null, user, req.flash('success', 'Bienvenido, ' + user.username))
}else{
done(null, false, req.flash('message', 'ContraseƱa incorrecta'))
}
} else {
return done(null, false, req.flash('message', 'El usuario no existe'))
}
}));
passport.use('local.signup', new LocalStrategy({
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true
}, async (req, username, password, done) => {
const newUser = {
username: username,
password: password
};
//newUser.password = await helpers.encryptPassword(password);
const result = await pool.query('INSERT INTO userr SET ?', [newUser])
newUser.id_user = result.insertId;
return done(null, newUser);
}));
passport.serializeUser((user, done) => {
console.log(user)
done(null, user.id_user)
});
passport.deserializeUser(async (id_user, done) => {
const rows = await pool.query('SELECT * FROM userr WHERE ID = ?', [id_user]);
done(null, rows[0]);
});
And this is my authentication.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
const { route } = require('./usuario');
router.get('/signup', (req, res) => {
res.render('auth/signup')
});
router.post('/signup', passport.authenticate('local.signup', {
successRedirect: '/profile',
failureRedirect: '/signup',
failureFlash: true
}));
router.get('/signin', (req, res) => {
res.render('auth/signin')
});
router.post('/signin', (req, res, next) => {
passport.authenticate('local.signin',{
successRedirect: '/profile',
failureRedirect: '/signin',
failureFlash: true
})(req, res, next);
})
router.get('/profile', (req, res) => {
res.render('profile');
});
module.exports = router;
I tried to use a different route, I forced out a session (it worked with a deserialize error I had), I redid the login step with completely different variables and a different database but I still got the same response.
I was developing a little software with registration and login forms in NodeJS. The code is blocked by this error "TypeError: initializePassport is not a function" at line 14 of server.js file.
This is the file server.js:
if (process.env.NODE_ENV !== "production"){
require("dotenv").config()
}
const express = require("express")
const app = express()
const bcrypt = require("bcryptjs")
const passport = require("passport")
const flash = require("express-flash")
const session = require("express-session")
const initializePassport = require("./passport-config")
initializePassport(
passport,
email => users.find(user => user.email === email),
id => users.find(user => user.id === id)
)
const users = []
app.set("view-engine", "ejs")
app.use(express.urlencoded({extended:false}))
app.use(flash())
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.get("/", (req, res) => {
res.render("index.ejs")
})
app.get("/login", (req, res) => {
res.render("login.ejs")
})
app.post("/login", passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login",
failureFlash: true
}))
app.post("/register", async (req, res) => {
try{
const hashedPassword = await bcrypt.hash(req.body.password, 10)
users.push({
id: Date.now().toString(),
name: req.body.name,
email: req.body.email,
password: hashedPassword
})
res.redirect("/login")
} catch {
res.redirect("/register")
}
console.log(users)
})
app.get("/register", (req, res) => {
res.render("register.ejs")
})
app.listen(3000)
and this is the passport-config.js:
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require("bcryptjs")
function initialize(passport, getUserByEmail) {
const authenticateUser = async (email, password, done) => {
const user = getUserByEmail(email)
if(user==null){
return done(null, false, {message:"Non ci sono utenti con questo nome"})
}
try{
if(await bcrypt.compare(password,user.password)){
return done(null, user)
} else {
return done(null, false, {message:"Password Errata"})
}
} catch (e) {
return done(e)
}
}
passport.use(new LocalStrategy({ usernameField:"email"},
authenticateUser))
passport.serializeUser((user, done) => done(null, user.id))
passport.deserializeUser((id, done) => {
return done(null, getUserById(id))
})
}
module.export = initialize
I tried to rename the const "initializePassport" or restarting the server but it doesn't work. At the start the server will block there on the same error.
I also tried changing the function I export from the passport-config.js.
Any other solutions? Tnx
I think that it is module.exports = initialize and not module.export = initialize.
If you wanna a named exports you use only exports = value
Try with this way: module.exports for default exports.
passport-config.js
function initialize() {}
exports.initialize = initialize
server.js
const initializePassport = require("./passport-config").initialize
initializePassport()
I am using nodeJS with the expressJS server framework. This issue is regarding passportJS not saving more than 1 user to MongoDB.
Firstly, I set up email registration with passport-local and got that to work fine. Secondly, I set up passport-facebook which essentially broke my email registration somehow. Each registration (email & facebook) now only log in just 1 user, I have to keep deleting the user from mongodb to register again. When there is 1 user in the database and I try to register another - I receive the error below.
process.nextTick(function() { throw err; });
^
TypeError: Cannot read property '1' of null at model.mongodbErrorHandler (/Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose-mongodb-errors/lib/plugin.js:19:49)
at next (/Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/node_modules/kareem/index.js:145:14)
at Kareem.execPost (/Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/node_modules/kareem/index.js:193:3)
at /Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/lib/model.js:219:35
at /Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/lib/model.js:152:9
at /Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/node_modules/mongodb/lib/collection.js:524:20
at /Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/node_modules/mongodb/lib/collection.js:658:14
at handleCallback (/Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/node_modules/mongodb/lib/utils.js:95:56)
at /Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/node_modules/mongodb/lib/bulk/unordered.js:465:9
at handleCallback (/Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/node_modules/mongodb/lib/utils.js:95:56)
at resultHandler (/Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/node_modules/mongodb/lib/bulk/unordered.js:413:5)
at /Users/tlr/Dropbox/Websites/app-one/node_modules/mongoose/node_modules/mongodb-core/lib/connection/pool.js:455:18
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
I think the issue may lie around the User Schema because each Strategy saves different user information. Thus, local & facebook may not be marrying up properly in the database which causes an error? Correct me if I'm wrong.
The main files to look at are my userSchema (User.js), my routes file (index.js) where I include my FB Strategy and module imports, and my controller files (userController.js, authController.js) where I export my modules and functions.
User.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
mongoose.Promise = global.Promise;
const md5 = require('md5');
const validator = require('validator');
const mongodbErrorHandler = require('mongoose-mongodb-errors');
const passportLocalMongoose = require('passport-local-mongoose');
const userSchema = new Schema({
name: {
type: String,
required: 'Please supply a name',
trim: true,
},
email: {
type: String,
unique: true,
lowercase: true,
trim: true,
required: 'Please supply an email address',
validate: [validator.isEmail, 'Invalid Email Address']
},
id: String,
token: String
});
userSchema.plugin(passportLocalMongoose, { usernameField: 'email' });
userSchema.plugin(mongodbErrorHandler);
module.exports = mongoose.model('User', userSchema);
index.js
const express = require('express');
const mongoose = require('mongoose');
const passport = require('passport');
const User = mongoose.model('User');
const authIDs = require('../../oauth');
const authController = require('../controllers/authController');
const userController = require('../controllers/userController');
const FacebookStrategy = require('passport-facebook').Strategy;
const router = express.Router();
passport.use(new FacebookStrategy({
clientID: authIDs.facebook.clientID,
clientSecret: authIDs.facebook.clientSecret,
callbackURL: authIDs.facebook.callbackURL,
profileFields: ['id', 'emails', 'name'],
passReqToCallback : true
},
function(req, accessToken, refreshToken, profile, done) {
const newUser = new User();
newUser.id = profile.id;
newUser.token = accessToken;
newUser.name = profile.name.givenName;
newUser.email = profile.emails[0].value;
process.nextTick( function() {
User.findOne({id: profile.id}, (err, user) => {
if (err) {
return done(err);
}
if (!user) {
newUser.save().then( user => {
done( null, user );
} ).catch( err => {
done( err );
} );
} else {
return done(null, user);
}
});
});
}
));
router.get( '/login', userController.loginForm);
router.post( '/login', authController.login);
router.get( '/register', userController.registerForm);
router.post( '/register',
userController.validateRegister,
userController.register,
authController.login
);
router.get('/auth/facebook', authController.fbauth);
router.get('/auth/facebook/callback', authController.fbcallback);
router.get( '/logout', authController.logout);
router.get('/', (req, res) => {
res.render('home');
});
module.exports = router;
userController.js
const mongoose = require('mongoose');
const User = mongoose.model('User');
const promisify = require('es6-promisify');
exports.loginForm = (req, res) => {
res.render('login')
};
exports.registerForm = (req, res) => {
res.render('register')
};
exports.validateRegister = (req, res, next) => {
// express validator methods below
req.sanitizeBody('name');
req.checkBody('name', 'You must supply a name!').notEmpty();
req.checkBody('email', 'That email is not valid!').isEmail();
req.sanitizeBody('email').normalizeEmail({
remove_dots: false,
remove_extension: false,
gmail_remove_subaddress: false
});
req.checkBody('password', 'Password cannot be blank!').notEmpty();
req.checkBody('password-confirm', 'Confirmed password cannot be blank!').notEmpty();
req.checkBody('password-confirm', 'Oops! Your passwords do not match').equals(req.body.password);
const errors = req.validationErrors();
if (errors) {
req.flash('error', errors.map(err => err.msg));
res.render('register', { body: req.body, flashes: req.flash() });
return;
}
next();
};
exports.register = async (req, res, next) => {
const user = new User({ name: req.body.name, email: req.body.email});
const register = promisify(User.register, User);
await register(user, req.body.password);
next();
};
authController.js
const passport = require('passport');
const mongoose = require('mongoose');
const User = mongoose.model('User');
exports.login = passport.authenticate('local', {
failureRedirect: '/login',
failureFlash: 'Failed Login!',
successRedirect: '/',
successFlash: 'You are now logged in!'
});
exports.fbauth = passport.authenticate('facebook', {scope: ['email']});
exports.fbcallback = passport.authenticate('facebook', {
failureRedirect: '/login',
failureFlash: 'Failed Login!',
successRedirect: '/',
successFlash: 'You are now logged in!'
});
exports.logout = (req, res, next) => {
req.logout();
req.flash('success', 'You successfully logged out!');
res.redirect('/login')
};
Any suggestions on a fix would be suuuuuuuuper duuuuuuper highly appreciated.
OH MY GOD after hours of trying, like most problems solved in coding, this one was terribly embarrassing.
Because I'm using the code as mentioned in the question above, you can see I'm implementing both a local email registration as well as a passport-facebook authentication. So... What was causing that confusing error was the following code was like this:
passport.serializeUser(User.serializeUser(), function(user, done) {
done(null, user.id);
});
passport.deserializeUser(User.deserializeUser(), function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
instead of simply being like this:
passport.serializeUser(User.serializeUser(), function(user, done) {
done(null, user);
});
passport.deserializeUser(User.deserializeUser(), function(user, done) {
done(null, user);
});
I am trying to code a mean authentication app. Right now i can create user in mongodb via postman but when i try to authenticate it,if it has wrong username or password it gives proper feedback,wrong password etc, but if it matches correct username and password on database, server shutdowns, it doesnt gives any feedback on postman and it gives the following error on server terminal:
(node:11262) DeprecationWarning: Mongoose: mpromise (mongoose's
default promise library) is deprecated, plug in your own promise
library instead: http://mongoosejs.com/docs/promises.html
/home/cagdas/Desktop/basictest/node_modules/jsonwebtoken/sign.js:90
throw err;
^
Error: Expected object
at validate
(/home/cagdas/Desktop/basictest/node_modules/jsonwebtoken
/sign.js:35:11) at Object.module.exports [as sign]
(/home/cagdas/Desktop/basictest/node_modules/jsonwebtoken
/sign.js:101:7) at User.comparePassword
(/home/cagdas/Desktop/basictest/routes/users.js:40:26)
at bcrypt.compare (/home/cagdas/Desktop/basictest/models/user.js:52:6)
at
/home/cagdas/Desktop/basictest/node_modules/bcryptjs/dist
/bcrypt.js:297:21
at /home/cagdas/Desktop/basictest/node_modules
/bcryptjs/dist/bcrypt.js:1353:21
at Immediate.next (/home/cagdas/Desktop/basictest/node_modules
/bcryptjs/dist/bcrypt.js:1233:21)
at runCallback (timers.js:672:20)
at tryOnImmediate (timers.js:645:5)
at processImmediate [as _immediateCallback] (timers.js:617:5)
This is my code:
app.js:
const express = require('express') ;
const path = require('path');
const bodyParser = require('body-parser');
const cors = require('cors');
const passport = require('passport');
const mongoose = require('mongoose');
const config = require('./config/database');
// Connect to Database
mongoose.connect(config.database, { useMongoClient: true });
// On Connection
mongoose.connection.on('connected', () => {
console.log('Connected to database '+config.database);
});
// On Error
mongoose.connection.on('error', (err) =>{
console.log('Database error: '+err);
});
const app = express();
const users = require('./routes/users');
// Port Number
const port = 3000;
// Cors Middleware
app.use(cors());
// Set Static Folder
app.use(express.static(path.join(__dirname, 'public')));
// Body Parser Middleware
app.use(bodyParser.json());
// Passport Middleware
app.use(passport.initialize());
app.use(passport.session());
require('./config/passport')(passport);
app.use('/users', users);
// Index Route
app.get('/', (req, res) => {
res.send('Invalid Endpoint');
});
// Start Server
app.listen(port, () => {
console.log('Server started on port '+port);
});
users.js:
const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
const User = require('../models/user');
const config = require('../config/database');
// Register
router.post('/register', (req, res, next) => {
let newUser = new User({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: req.body.password
});
User.addUser(newUser, (err, user) =>{
if(err){
res.json({success: false, msg:'Failed to register user'});
} else {
res.json({success: true, msg:'User registered'});
}
});
});
// Authenticate
router.post('/authenticate', (req, res, next) => {
const username = req.body.username;
const password = req.body.password;
User.getUserByUsername(username, (err, user) => {
if(err) throw err;
if(!user){
return res.json({success: false, msg: 'User not found'});
}
User.comparePassword(password, user.password, (err, isMatch) => {
if(err) throw err;
if(isMatch){
const token = jwt.sign(user, config.secret, {
expiresIn: 86400 // 1 day
});
res.json({
success: true,
token: 'JWT ' +token,
user: {
id: user._id,
name: user.name,
username: user.username,
email: user.email
}
});
} else {
return res.json({success: false, msg: 'Wrong Password'});
}
});
})
});
// Profile
router.get('/profile', (req, res, next) => {
res.send('PROFILE');
});
module.exports = router;
database.js:
module.exports = {
database: 'mongodb://localhost:27017/basictest',
secret: '123456789'
}
user.js:
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const config =require('../config/database');
// User Schema
const UserSchema = mongoose.Schema({
name: {
type: String
},
email: {
type: String,
required: true
},
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
const User = module.exports = mongoose.model('User', UserSchema);
module.exports.getUserById = function(id, callback){
User.findById(id, callback);
}
module.exports.getUserByUsername = function(username, callback){
const query = {username: username}
User.findOne(query, callback);
}
module.exports.addUser = function(newUser, callback){
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err) throw err;
newUser.password = hash;
newUser.save(callback);
});
});
}
module.exports.comparePassword = function(candidatePassword, hash,
callback){
bcrypt.compare(candidatePassword, hash, (err, isMatch) => {
if(err) throw err;
callback(null, isMatch);
});
}
passport.js
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../models/user');
const config = require('../config/database');
module.exports = function(passport){
let opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('jwt');
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, (jwt_payload, done) => {
User.getUserById(jwt_payload._id, (err, user) => {
if(err){
return done (err, false);
}
if(user){
return done(null, user);
} else {
return done(null, false);
}
});
}));
}
Solution - not user only { data: user }
const token = jwt.sign({data: user}, config.secret, {
expiresIn: 604800 // 1 week
});
Got the same error for a while and I suggest that you recreate a new object user (without the hashed password for security reason) and insert it into the sign function.
let restrictedUser = {
id: user._id,
username: user.username,
name: user.name,
email: user.email
}
const token = jwt.sign(restrictedUser, config.secret, {
expiresIn: "7d"
})
Hope this will help.
Not sure about this, But you can try this
"npm remove mongoose"
Then
"npm install mongoose#4.10.8 --save"
Hope it will help you..
Thanks...