our passport login worked fine before we added a database.
Now we seem to be saving an ID that is not a facebook ID
it is saving _ID and we cannot retrieve facebook data from our database.
So I am guessing the problem is that it is not saving to the database correctly,
But unsure why.
passport.serializeUser(function(user, done) {
console.log('serializeUser: ' + user.id)
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log(id)
User.findById(id, function(err, user){
console.log(user)
if(!err) done(null, user);
else done(err, null)
})
});
var sessionData = session({
store: sessionStore.createSessionStore(),
secret: "your_secret",
cookie: { maxAge: 2628000000 },
resave: true,
saveUninitialized: true
});
passport.use(new FacebookStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
callbackURL: "/auth/facebook/callback",
profileFields: ['id', 'name'],
enableProof: false
},
function(accessToken, refreshToken, profile, done) {
console.log("accesstoken: " + accessToken + "refreshToken " + refreshToken + "profile: " + profile.id + "done:" + done)
User.findOne({
'facebook.id': profile.id
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
user = new User({
facebookID: profile.id,
name: profile.displayName,
provider: 'facebook',
facebook: profile._json
});
user.save(function(err) {
if (err) console.log(err);
return done(err, user);
});
} else {
//found user. Return
return done(err, user);
}
});
}
));
var app = express();
app.set('views', __dirname + '/app/views');
app.set('view engine', 'ejs');
app.use(sessionData);
app.use(logger("combined"));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(methodOverride());
app.use(session({
secret: "keyboard cat",
saveUninitialized: true, // (default: true)
resave: true, // (default: true)
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(__dirname + '/app/public'));
app.use(express.static(__dirname + '/'));
var http = require('http');
server = http.createServer(app);
io = require('socket.io')(server);
app.get('/', function(req, res){
res.render('index', { user: req.user });
});
app.get('/account', ensureAuthenticated, function(req, res){
User.findById(req.session.passport.user, function(err, user) {
if(err) {
console.log(err);
} else {
res.render('account', { user: user});
}
});
});
app.get('/login', function(req, res){
res.render('login', { user: req.user });
});
app.get('/auth/facebook',
passport.authenticate('facebook'));
app.get('/auth/facebook/callback',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
});
app.get('/logout', function(req, res){
req.logout();
res.redirect('/');
});
Repo is on a branch
https://github.com/5-minute-catchup/ANEWREPO/tree/mongodb
User.findOne({
'facebook.id': profile.id
}
Should be:
User.findOne({
facebookID: profile.id
}
Related
So this is my code that is giving me problems with the authentification. I dont know how to get the id since is already created.
require('dotenv').config()
const express = require ("express");
const bodyParser = require ("body-parser");
const ejs = require ("ejs");
const mongoose = require ("mongoose")
const md5 = require ("md5");
const saltRounds = 10;
var bcrypt = require('bcryptjs');
const session = require('express-session');
const passport = require ("passport");
const passportLocalMongoose = require ("passport-local-mongoose");
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const findOrCreate = require ("mongoose-findorcreate");
const app = express();
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});
const userSchema = new mongoose.Schema({
email: String,
password: String,
googleID: 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",
},
function(accessToken, refreshToken, profile, cb) {
console.log(profile);
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
app.use(express.static("public"));
app.set("view engine", "ejs");
app.use (bodyParser.urlencoded({
extended:true
}));
app.get ("/", function (req, res) {
res.render("home");
});
app.get('/auth/google',
passport.authenticate('google', {scope: ['profile', 'email']})
);
app.get('/auth/google/callback',
passport.authenticate('google', {
successRedirect: '/profile',
failureRedirect: '/fail'
})
);
app.get('/auth/google/secrets',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/secrets');
});
app.get ("/login", function (req, res) {
res.render("login");
});
app.get ("/register", function (req, res) {
res.render("register");
});
app.get("/secrets", function (req,res) {
if (req.isAuthenticated()){
res.render("secrets");
}else {
res.rendirect("/login");
}
})
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.authenticated("local")(req,res, function() {
res.redirect("/secrets");
});
}
});
});
app.listen(3000, function() {
console.log("Server started on port 3000")
});
So when Im trying to run my code but the same error appears all the time in my system.
ReferenceError: id is not defined
at /Users/vivianaandrango/Desktop/Alberto/Secrets code/app.js:55:20
at pass (/Users/vivianaandrango/Desktop/Alberto/Secrets code/node_modules/passport/lib/authenticator.js:291:9)
at Authenticator.serializeUser (/Users/vivianaandrango/Desktop/Alberto/Secrets code/node_modules/passport/lib/authenticator.js:296:5)
at SessionManager.logIn (/Users/vivianaandrango/Desktop/Alberto/Secrets code/node_modules/passport/lib/sessionmanager.js:14:8)
at IncomingMessage.req.login.req.logIn (/Users/vivianaandrango/Desktop/Alberto/Secrets code/node_modules/passport/lib/http/request.js:39:26)
at Strategy.strategy.success (/Users/vivianaandrango/Desktop/Alberto/Secrets code/node_modules/passport/lib/middleware/authenticate.js:256:13)
at verified (/Users/vivianaandrango/Desktop/Alberto/Secrets code/node_modules/passport-oauth2/lib/strategy.js:189:20)
at /Users/vivianaandrango/Desktop/Alberto/Secrets code/app.js:73:14
at /Users/vivianaandrango/Desktop/Alberto/Secrets code/node_modules/mongoose-findorcreate/index.js:47:11
at /Users/vivianaandrango/Desktop/Alberto/Secrets code/node_modules/mongoose/lib/model.js:4999:1
UPDATE
When I add to the code
passport.serializeUser(function(user, done, id) {
done(null, user, id);
});
The system gives me back all my data but on Hyper I get all the information.
I am getting a weird error as all of my login system are working correctly which include local login in system and Google and Facebook login. The problem arose when I try to try to register with google when I have already register the Facebook account and I try to register Google account it gives E11000 duplicate key error collection and vice versa for Facebook. I am using passport.js for authentication and login system here is some code:
const express = require("express");
const app = express();
const BodyParser = require('body-parser');
const ejs = require('ejs');
const session = require("express-session");
const passport = require("passport");
const LocalStratgy = require('passport-local').Strategy;
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const FacebookStrategy = require("passport-facebook").Strategy;
const passportLocalMongoose = require("passport-local-mongoose");
const findOrCreate = require('mongoose-findorcreate');
const mongoose = require('mongoose');
const { static } = require("express");
app.use(express.static('public'));
app.set('view engine', 'ejs');
app.use(BodyParser.urlencoded({extended: true}));
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect('mongodb://localhost/userDB', {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.set('useCreateIndex', true);
const userSchema = new mongoose.Schema( {
email: String,
password: String,
googleId: String,
facebookId: String
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
/* userSchema.plugin(encrypt,{secret: process.env.SECRET, encryptedFields: ['password']}); */
const User = new mongoose.model("User", userSchema);
passport.use(new LocalStratgy(User.authenticate()));
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_SECRETS,
callbackURL: "http://localhost:3000/auth/google/secrets",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FB_APP_SECRETS,
callbackURL: "http://localhost:3000/auth/facebook/secrets"
},
function(accessToken, refreshToken, profile, cb) {
console.log(profile);
User.findOrCreate({ facebookId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
app.get("/" ,(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 secrets.
res.redirect('/secrets');
});
app.get('/auth/facebook',
passport.authenticate('facebook'));
app.get('/auth/facebook/secrets',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, secrets .
res.redirect('/secrets');
});
app.get("/login" ,(req, res) => {
res.render('login');
});
app.get("/register" ,(req, res) => {
res.render('register');
});
app.get("/secrets", (req, res) => {
if(req.isAuthenticated()){
res.render("secrets");
}else{
res.redirect("/login");
}
})
app.post("/register", (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", (req, res) => {
const user = new User({
username: req.body.username,
password: req.body.password
});
req.login(user, err => {
if(err){
console.log(err);
}else{
passport.authenticate("local")(req, res, function(){
res.redirect("/secrets");
});
}
})
});
app.get("/logout", (req, res) => {
req.logOut();
res.redirect("/");
})
Note: Individually the Facebook and Google authentication works like a charm but when both used together it throws an error. I store Facebook and Google id in my database as in screenshot: and local system works just fine with Facebook and Google no problem there.
If you follow passport documentation then it's probably not so correct for your usage.
The following will just create an account base on facebook Id
User.findOrCreate({ facebookId: profile.id }, function (err, user) {
return cb(err, user);
});
The following will just create an account base on google Id
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
However, I'm quite sure your user is identified by email.
Your above queries will create 2 separate _id with same email address.
Hence your query should be corrected to similar as follows
User.updateOne({ email: profile.email }, { googleId: profile.id }, { upsert: true })
And
User.updateOne({ email: profile.email }, { facebookId: profile.id }, { upsert: true })
The above will check whether email exist, if it does, update googleId. If it doesn't exist, create a new user.
In addition, your schema is missing the username field
I'm trying to assign the user to a cookie when someone logs in, but looks like passport is not assigning the data to the cookie. Below you can find the code:
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(passport.initialize());
//Use session
app.use(passport.session({ secret: '=Mx;D5F}t&iJZ&w-g;FLK:%QavZgZt', cookie: { maxAge: 0 }, resave: true, saveUninitialized: true }))
app.use(express.static('server/public'));
//Set view engine
app.set('views', 'server/views')
app.set('view engine', 'pug');
//Set passport local strategy
passport.use(new LocalStrategy({ usernameField: "email" },
function (email, password, done) {
User.findOne({ 'email': email }, async function (err, user) {
console.log('user requested password caught in passport: ', password);
if (err) { return done(err); }
if (!user) {
return done(null, false, console.log('Wrong username'));
}
return await user.validatePassword(password, function (err, result) {
if (err || !result) return done(null, false, console.log('Wrong Password'));
return done(null, user);
})
});
}
));
// serialize user object
passport.serializeUser(function (user, done) {
done(null, user.id);
});
// deserialize user object
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
})
});
and this is the login route:
//Route for user login
app.post('/auth/local/signin',
function (req, res, next) {
passport.authenticate('local', function (err, user, info) {
console.log(err);
console.log(user);
if (err) {
console.log('passport.authenticate: error')
} else if (!user) {
console.log('passport.authenticate: user')
} else {
console.log('next handler')
console.log('Cookie assigned: ' + req.user)
return res.redirect('/dashboard')
}
return res.redirect('/login')
})(req, res, next)
}
)
As you can see, I have tried to log req.user which is giving me back undefined.
However, the console.log(user) gives me back the user from the DB, which is what I want.
Note: there are many similar questions but I've gone through all of them and none of the solutions work.
Hi,
I've tried every solution on the net, bug still persists.
I'm building a simple CRUD app, and I'm currently struggling with passportjs's req.isAuthenticated().
The user is definitely being authenticated, as console.log(req.user) in passport.authenticate returns the user object, and req.session.passport has the user id.
After the redirect though, even if the redirect is async, user is undefined and req.session.passport is empty. It's as if the session is reset.
Here's the code:
app.js
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var session = require('express-session');
var passport = require('passport');
var flash = require('connect-flash');
var index = require('./routes/index');
var users = require('./routes/users');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/bootstrap', express.static(path.join(__dirname + '/node_modules/bootstrap/dist')));
app.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: true,
cookie: {
maxAge: 5 * 60 * 1000
}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(function(req, res, next) {
res.locals.messages = require("express-messages")(req, res);
next();
});
app.get('*', function(req, res, next) {
console.log(req.method, ":", req.url);
res.locals.user = req.user || null;
next();
});
app.use("/", index);
app.use("/users", users);
var port = 4000;
app.listen(port);
module.exports = app;
index.js
var express = require('express');
var router = express.Router();
router.get('/', isLoggedIn, function(req, res) {
if (req.user) {
console.log(req.user.username);
}
res.render('homepage');
});
function isLoggedIn(req, res, next) {
console.log("passport: ", req.session.passport); //passport:{}
if (req.isAuthenticated()) {
return next();
}
res.redirect('/users/login');
}
module.exports = router;
users.js
var express = require('express');
var router = express.Router();
var mongojs = require('mongojs');
var db = mongojs('usersDB', ['users']);
var bcrypt = require('bcryptjs');
var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;
router.get('/login', function(req, res) {
res.render('login');
});
router.get('/signup', function(req, res) {
res.render('signup');
});
router.post('/signup', function(req, res) {
db.users.findOne({
username: req.body.name
}, function(err, user) {
if (err) {
return done(err);
}
if (user) {
console.log("nope");
req.flash("error", "Username taken. Choose a different username.");
return res.redirect('/users/signup');
}
var password = req.body.password;
bcrypt.genSalt(10, function(err, salt) {
if (err) {
return done(err);
}
bcrypt.hash(password, salt, function(err, hash) {
if (err) {
return done(err);
}
var user = {
username: req.body.name,
email: req.body.email,
phone: req.body.phone,
password: hash
}
db.users.insert(user, function(err, result) {
if (err) {
return done(err);
}
console.log("registered", user)
res.render("homepage", {
user: user
});
});
});
});
});
}); //sorry for the callback hell..works fine
passport.serializeUser(function(user, done) {
return done(null, user._id);
});
passport.deserializeUser(function(id, done) {
db.users.findOne({
id: mongojs.ObjectId(id)
}, function(err, user) {
return done(err, user);
});
});
passport.use('loginStrategy', new LocalStrategy({
passReqToCallback: true,
usernameField: 'username',
passwordField: 'password'
},
function(req, username, password, done) {
db.users.findOne({
username: username
}, function(err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, req.flash('error', "Invalid username."));
}
bcrypt.compare(password, user.password,
function isMatch(err, isMatch) {
if (err) {
return done(err);
}
if (!isMatch) {
return done(null, false, req.flash('error', "Oops. Incorrect password."));
}
return done(null, user, req.flash('success', "Welcome " + user.username + ", you are now logged in."));
});
});
}));
router.post('/login', function(req, res, next) {
passport.authenticate('loginStrategy', function(err, user, info) {
if (info) {
req.flash('error', info.message);
}
if (err) {
return next(err);
}
if (!user) {
return res.redirect('/users/login');
}
req.logIn(user, function(err) {
if (err) {
return next(err);
}
//callback redirect after saving session.
req.session.save(function() {
console.log(req.session.passport); //{ user: 59ceb263dae7a4270087ae57 }
res.redirect('/');
});
});
})(req, res, next);
});
router.get('/logout', function(req, res) {
req.logout();
res.redirect('/users/login');
});
module.exports = router;
I would really appreciate some help, as this is seems to be a common bug, but none of the workarounds work for me.
This seems to be related to the method you are using to store the user creds. Please note, Chrome and IE have different quirks about local vs session storage. Try this in chrome, Passport JS will store the response in either Local or Session storage - you should interrogate those storage mechanisms to verify the user's credentials are in them.
In chrome, go to the F12 debug tools and look in your session and local storage:
Please let us know the browser you are using, and if using Chrome makes a difference.
im working on a node passport login authentication but im stack on this error which makes it hard for me to run my node server
/home/emil/Documents/myapp/app/routes.js:14
app.post('/login', passport.authenticate('local-login', {
^
TypeError: Cannot read property 'authenticate' of undefined
how can i fix it?
my code:
server.js
var express = require('express');
var app = express();
var port = 8080;
var cookieParser = require('cookie-parser');
var session = require('express-session');
var morgan = require('morgan');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var passport = require('passport');
var configDB = require('./config/database.js');
mongoose.connect(configDB.url);
app.use(passport.initialize());
app.use(passport.session());
app.use(morgan('dev'));
app.use(cookieParser());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(session({
secret: 'anystringoftext',
saveUninitialized: true,
resave: true
}));
app.set('view engine', 'ejs');
//app.use('/', function(req, res){
// res.send('Our First Express program!');
// console.log(req.cookies);
// console.log('===============');
// console.log(req.session);
//});
require('./app/routes.js')(app);
app.listen(port);
console.log('Server running on port: ' + port);
routes.js:
var User = require('./models/user');
module.exports = function (app, passport) {
app.get('/', function (req, res) {
res.render('index.ejs');
});
app.get('/login', function (req, res) {
res.render('login.ejs', {
message: req.flash('loginMessage')
});
});
app.post('/login', passport.authenticate('local-login', {
successRedirect: '/profile',
failureRedirect: '/login',
failureFlash: true
}));
app.get('/signup', function (req, res) {
res.render('signup.ejs', {
message: req.flash('signupMessage')
});
});
app.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/',
failureRedirect: '/signup',
failureFlash: true
}));
app.get('/profile', isLoggedIn, function(req, res){
res.render('profile.ejs', { user: req.user });
});
app.get('/:username/:password', function (req, res) {
var newUser = new User();
newUser.local.username = req.params.username;
newUser.local.password = req.params.password;
console.log(newUser.local.username + " " + newUser.local.password);
newUser.save(function (err) {
if (err)
console.log(err);
});
res.send("Success!");
})
};
function isLoggedIn(req, res, next) {
if(req.isAuthenticated()){
return next();
}
res.redirect('/login');
}
passport.js
var LocalStrategy = require('passport-local').Strategy;
var User = require('../app/models/user');
module.exports - function(passport) {
passport.serializeUser(function(usser, done){
done(null, user.id);
});
passport.deserializeUser(function(id, done){
User.findById(id, function(err, user){
done(err, user);
});
});
passport.use('local-signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done){
process.nextTick(function(){
User.findOne({'local.username': email}, function(err, user){
if(err)
return done(err);
if(user){
return done(null, false, req.flash('signupMessage', 'That account exists'));
} else {
var newUser = new User();
newUser.local.username = email;
newUser.local.password = password;
newUser.save(function(err){
if(err)
throw err;
return done(null, newUser);
})
}
})
});
}));
passport.use('local-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
},
function(req, email, password, done){
process.nextTick(function(){
User.findOne({ 'local.username': email}, function(err, user){
if(err)
return done(err);
if(!user)
return done(null, false, req.flash('loginMessage', 'No user found'));
if(user.local.password != password)
return done(null, false, req.flash('loginMessage', 'invalid password'));
}
return done(null, user);
})
})
}
))
You have not passed passport to the routes. require('./app/routes.js')(app); should be require('./app/routes.js')(app, passport) in server.js;