Passport - Error: Can't set headers after they are sent - javascript

I know variations of this questions have been asked multiple times. My understanding is that you basically have to watch your if/else logic and make sure that done isn't being called multiple times.
Twitter and Google work fine. Facebook is giving me this error though:
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (/Users/azerner/code/mean-starter/node_modules/express/lib/response.js:718:10)
at ServerResponse.location (/Users/azerner/code/mean-starter/node_modules/express/lib/response.js:835:8)
at ServerResponse.redirect (/Users/azerner/code/mean-starter/node_modules/express/lib/response.js:874:8)
at complete (/Users/azerner/code/mean-starter/node_modules/passport/lib/middleware/authenticate.js:241:26)
at /Users/azerner/code/mean-starter/node_modules/passport/lib/middleware/authenticate.js:250:15
at pass (/Users/azerner/code/mean-starter/node_modules/passport/lib/authenticator.js:427:14)
at Authenticator.transformAuthInfo (/Users/azerner/code/mean-starter/node_modules/passport/lib/authenticator.js:449:5)
at /Users/azerner/code/mean-starter/node_modules/passport/lib/middleware/authenticate.js:247:22
at /Users/azerner/code/mean-starter/node_modules/passport/lib/http/request.js:51:7
at pass (/Users/azerner/code/mean-starter/node_modules/passport/lib/authenticator.js:273:43)
at serialized (/Users/azerner/code/mean-starter/node_modules/passport/lib/authenticator.js:282:7)
at /Users/azerner/code/mean-starter/server/passport.js:17:5
at pass (/Users/azerner/code/mean-starter/node_modules/passport/lib/authenticator.js:290:9)
at Authenticator.serializeUser (/Users/azerner/code/mean-starter/node_modules/passport/lib/authenticator.js:295:5)
at IncomingMessage.req.login.req.logIn (/Users/azerner/code/mean-starter/node_modules/passport/lib/http/request.js:48:29)
passport.js
var LocalStrategy = require('passport-local').Strategy;
var FacebookStrategy = require('passport-facebook').Strategy;
var TwitterStrategy = require('passport-twitter').Strategy;
var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
var mongoose = require('mongoose');
var User = mongoose.model('User');
var Local = mongoose.model('Local');
var Facebook = mongoose.model('Facebook');
var Twitter = mongoose.model('Twitter');
var Google = mongoose.model('Google');
var bcrypt = require('bcrypt');
var config = require('./config.json');
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User
.findById(id).populate('local').exec()
.then(function(user) {
console.log('deserializeUser found user: ', user);
done(null, user);
}, done)
;
});
// LOCAL
passport.use(new LocalStrategy(function(username, password, done) {
Local
.findOne({ username: username })
.select('username role hashedPassword')
.exec()
.then(function(local) {
if (!local) {
return done(null, false);
}
var validPassword = bcrypt.compareSync(password, local.hashedPassword);
if (!validPassword) {
return done(null, false);
}
else {
User
.findOne({ local: local })
.populate('local')
.exec()
.then(function(user) {
return done(null, user);
})
;
}
})
;
}));
// FACEBOOK
passport.use(new FacebookStrategy({
clientID: config.facebookAuth.clientID,
clientSecret: config.facebookAuth.clientSecret,
callbackURL: config.facebookAuth.callbackURL
}, function(token, refreshToken, profile, done) {
// asynchronous
process.nextTick(function() {
Facebook
.findOne({ id: profile.id })
.select('id token')
.exec()
.then(function(facebook) {
if (facebook) {
User
.findOne({ facebook: facebook._id }).exec()
.then(function(user) {
return done(null, user);
})
;
}
else {
Facebook
.create({ id: profile.id, token: token })
.then(function(createdFacebook) {
User
.create({ facebook: createdFacebook })
.then(function(user) {
return done(null, user);
})
;
})
;
}
})
.then(function(err) {
return done(err);
})
;
});
}));
// TWITTER
passport.use(new TwitterStrategy({
consumerKey: config.twitterAuth.consumerKey,
consumerSecret: config.twitterAuth.consumerSecret,
callbackURL: config.twitterAuth.callbackURL
}, function(token, tokenSecret, profile, done) {
process.nextTick(function() {
Twitter
.findOne({ id: profile.id })
.select('id token')
.exec()
.then(function(twitter) {
if (twitter) {
User
.findOne({ twitter: twitter._id }).exec()
.then(function(user) {
return done(null, user);
})
;
}
else {
Twitter
.create({ id: profile.id, token: token })
.then(function(createdTwitter) {
User
.create({ twitter: createdTwitter })
.then(function(user) {
return done(null, user);
})
;
})
;
}
})
.then(null, function(err) {
return done(err);
})
;
});
}));
// GOOGLE
passport.use(new GoogleStrategy({
clientID: config.googleAuth.clientID,
clientSecret: config.googleAuth.clientSecret,
callbackURL: config.googleAuth.callbackURL
}, function(token, refreshToken, profile, done) {
process.nextTick(function() {
Google
.findOne({ id: profile.id })
.select('id token')
.exec()
.then(function(google) {
if (google) {
User
.findOne({ google: google._id }).exec()
.then(function(user) {
return done(null, user);
})
;
}
else {
Google
.create({ id: profile.id, token: token })
.then(function(createdGoogle) {
User
.create({ google: createdGoogle })
.then(function(user) {
return done(null, user);
})
;
})
;
}
})
.then(null, function(err) {
return done(err);
})
;
});
}));
};
auth.routes.js
var mongoose = require('mongoose');
var express = require('express');
var passport = require('passport');
var Auth = require('./auth.service.js');
try {
var User = mongoose.model('User');
}
catch(e) {
var User = mongoose.model('User', require('../users/user.model.js').UserSchema);
}
var router = express.Router();
// LOCAL
router.post('/login', passport.authenticate('local'), function(req, res) {
res.status(200).json(req.user);
});
router.get('/logout', Auth.isLoggedIn, function(req, res) {
req.logout();
res.status(204).end();
});
router.get('/current-user', Auth.isLoggedIn, function(req, res) {
res.status(200).json(req.user);
});
// FACEBOOK
router.get('/auth/facebook', passport.authenticate('facebook'));
router.get('/auth/facebook/callback',
passport.authenticate('facebook', {
successRedirect: '/',
failureRedirect: '/login'
})
);
// TWITTER
router.get('/auth/twitter', passport.authenticate('twitter'));
router.get('/auth/twitter/callback',
passport.authenticate('twitter', {
successRedirect: '/',
failureRedirect: '/login'
})
);
// GOOGLE
router.get('/auth/google', passport.authenticate('google', { scope: ['profile'] }));
router.get('/auth/google/callback',
passport.authenticate('google', {
successRedirect: '/',
failureRedirect: '/login'
})
);
module.exports = router;
It's also worth noting that I have been using this to block Facebook, but I unblocked it to work on this. I did the commands, force quit Chrome and reopened it, and now I can log into facebook.com fine.
Edit: Oh, and I checked MongoHub and it shows that the User (and Facebook subdocument) have been created.

Related

how to convert this Callback Authentication to Promise in nodejs mongoose

I am using Nodejs Mongoose here But when i Try to replace Callback to promise It Gives me an error
(Failed to serialize user into session)
Please Help Me........
var localStrategy = require('passport-local').Strategy;
const user = require('./mongoBase/userSc.js');
const bcrypt = require('bcryptjs');
module.exports = function(passport) {
passport.use(new localStrategy({ usernameField: 'email' }, (email, password, done) => {
email = email.toLowerCase();
user.findOne({ email: email }, (err, data) => {
if (err) throw err;
if (!data) {
return done(null, false, { message: "User Doesn't Exists.." });
}
bcrypt.compare(password, data.password, (err, match) => {
if (err) {
return done(null, false);
}
if (!match) {
return done(null, false, { message: "Password Doesn't Match" });
}
if (match) {
return done(null, data);
}
});
});
}));
passport.serializeUser(function(user, cb) {
cb(null, user.id);
});
passport.deserializeUser(function(id, cb) {
user.findById(id, function(err, user) {
cb(err, user);
});
});
}
// ---------------
// end of autentication statregy
Here is my code for passport with spotify, maybe it could help you some. If your question is answered by this answer, please click the checkbox beside the answer.
module.exports = function(passport) {
passport.use(
new SpotifyStrategy(
{
clientID: 'CLIENT ID',
clientSecret: 'CLIENT SECRET',
callbackURL: 'http://localhost:8888/auth/spotify/callback',
},
async (accessToken, refreshToken, expires_in, profile, done) => {
// Do async operations
async function checking() {
// Do async operations
}
await checking();
return done(null, profile);
}
)
);
// Serialize
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});

nodejs ajax local passport | user data req.user registered to user

I want to log in with ajax.
I want user information to be recorded in the request parameter.
But when I do it with ajax, user information is not registered in the request parameter.
so req.user --> undefined
he's turning.
How can I solve this?
local auth passport codes:
const LocalStrategy = require("passport-local").Strategy;
const passport = require("passport");
const bcrypt = require("bcrypt");
const User = require("../models/User");
passport.use(
"user-login",
new LocalStrategy(
{
usernameField: "email",
},
(email, password, done) => {
User.findOne(
{
email,
},
(err, user) => {
if (err) return done(err, null, "Bir hata olustu");
if (!user) {
return done(null, false, "Böyle bir email yok.");
}
bcrypt.compare(password, user.password, (err, res) => {
if (res) {
return done(null, user, "Başarıyla giriş yapıldı.");
} else {
return done(null, false, "Yanlış şifre girildi");
}
});
}
);
}
)
);
passport.serializeUser(function (user, done) {
console.log(user);
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
console.log(user);
done(err, user);
});
});
router:
module.exports.postLogin = async (req, res, next) => {
passport.authenticate("user-login", {
successRedirect: "/",
failureRedirect: "/users/login",
failureFlash: true,
successFlash: true,
})(req, res, next);
}
app.js middleware
app.use((req, res, next) => {
console.log(req.user);
next();
});
print:
POST /admin/login 302 2304.994 ms - 23
{
_id: 5fb8fa8c26cdfc239c4276b9,
username: 'tolgaand',
password: '$2b$10$XhifEgbN4mEiCGPvm/dF5.zHYlEPZW3Jhibjm4ABuhEeRJ34psYsu',
name: 'Tolga',
lastName: 'Çağlayan',
title: 'Javascript Geliştiricisi',
about: "mongodb'ye bağlandım olley",
phone: '+90 534 393 6238',
email: 'tolgaand#yandex.com',
location: 'İstanbul / Türkiye',
available: 'Müsait',
permission: 0,
__v: 0
}
{}
router with ajax (i want)
module.exports.postLogin = async (req, res, next) => {
passport.authenticate("user-login", (error, user, info) => {
if (error) {
return res.json({ success: false, message: info.message });
}
if (!user) {
return res.json({ success: false, message: info });
}
res.json({ success: true, message: info, user });
})(req, res, next);
};
print:
POST /admin/login 200 998.327 ms - 446
undefined
{}
how can I do this with jquery / ajax?
instead of undefined, I just want user information to be registered as above.

Error in sign up passport-local sign up routine

I'm building an app in Node, using Passport and local signup and sign in strategies. I just keep running into an issue. All the required modules etc. are there. The following sign in routine works fine:
passport.use('local-signin', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqTodone : true
}, function(req, email, password, done) {
User.findOne({ 'local.email' : email }, function(err, user) {
if (err)
return done(err);
if (!user)
return done(null, false, req.flash('message', 'User not found.'));
if (!user.validPassword(password))
return done(null, false, req.flash('message', 'Wrong password.'));
return done(null, user);
});
}));
However, the following sign up routine does not:
passport.use('local-signup', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
passReqTodone : true
}, function(req, email, password, done) {
console.log("signing up")
User.findOne({ 'local.email' : email }, function(err, user) {
if (err) {
return done(err);
} else if (user) {
return done(null, false, req.flash('message', 'That email address is already registered.'));
} else {
var newUser = new User();
}
// save the user
newUser.save(function(err) {
if (err) {
console.log("Error saving new user profile: " + err);
} else {
return done(null, newUser, req.flash('message', 'User account created'));
}
});
});
}))
Both routines are called within routes.js:
// POST : SIGNUP
app.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/',
failureRedirect: '/error',
failureFlash: true
}));
// POST : SIGNIN
app.post('/signin', passport.authenticate('local-signin', {
successRedirect: '/profile',
failureRedirect: '/',
failureFlash: true
}));
Any ideas where it might go wrong? As is, posting to /signup continuously results in a failureRedirect. My head is getting kinda sore from banging on the screen...
The only thing you need to change is:
if (!user.validPassword(password))
To
if (user.validPassword(password) === false)
I know, if (!user.validPassword(password)) is in examples on Passport.js official docs, but it is wrong.
I have just lost 2 hours of my life, figuring this out.
Use this code it will helps you to fix your problem
passport-authentication.js
var express=require('express');
var router = express.Router();
var passport = require('passport');
var User = require('../models/user');//user is schema
var Verify = require('./verify');//verify is a file where the user is verified
/* GET users listing. */
router.get('/', Verify.verifyOrdinaryUser,function(req, res, next) {
User.find({},function(err,user){
if(err) throw err;
res.json(user);
});
});
router.post('/register', function(req, res) {
User.register(new User({ username : req.body.username,Email:req.body.Email}),
req.body.password, function(err, user) {
if (err) {
return res.status(500).json({err: err});
}
if(req.body.firstname) {
user.firstname = req.body.firstname;
}
if(req.body.lastname) {
user.lastname = req.body.lastname;
}
user.save(function(err,user) {
passport.authenticate('local')(req, res, function () {
return res.status(200).json({status: 'Registration Successful!'});
});
});
});
});
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json({
err: info
});
}
req.logIn(user, function(err) {
if (err) {
return res.status(500).json({
err: 'Could not log in user'
});
}
var token = Verify.getToken(user);
res.status(200).json({
status: 'Login successful!',
success: true,
token: token
});
});
})(req,res,next);
});
router.get('/logout', function(req, res) {
req.logout();
res.status(200).json({
status: 'Bye!'
});
});
module.exports = router;
verify.js
var User = require('../models/user');
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
var config = require('../config.js');
exports.getToken = function (user) {
return jwt.sign(user, config.secretKey, {
expiresIn: 3600
});
};
exports.verifyOrdinaryUser = function (req, res, next) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secretKey, function (err, decoded) {
if (err) {
var err = new Error('You are not authenticated!');
err.status = 401;
return next(err);
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
var err = new Error('No token provided!');
err.status = 403;
return next(err);
}
};
hope this helps for you...

TypeError: User.findById is not a function on deserializeUser

i was working with passport auth (local and google strategy) and now it tells me "User.findById is not a function" on the "deserializeUser" function.
passport.js
const passport = require('passport');
const request = require('request');
const LocalStrategy = require('passport-local').Strategy;
const GoogleStrategy = require('passport-google-oauth').
const OAuthStrategy = require('passport-oauth').OAuthStrategy;
const OAuth2Strategy = require('passport-oauth').OAuth2Strategy;
const User = require('../routes/user');
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
/**
* Sign in using Email and Password.
*/
passport.use(new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
User.findOne({ email: email.toLowerCase() }, (err, user) => {
if (err) { return done(err); }
if (!user) {
return done(null, false, { msg: `Email ${email} not found.` });
}
user.comparePassword(password, (err, isMatch) => {
if (err) { return done(err); }
if (isMatch) {
return done(null, user);
}
return done(null, false, { msg: 'Invalid email or password.' });
});
});
}));
/**
* OAuth Strategy Overview
*
* - User is already logged in.
* - Check if there is an existing account with a provider id.
* - If there is, return an error message. (Account merging not supported)
* - Else link new OAuth account with currently logged-in user.
* - User is not logged in.
* - Check if it's a returning user.
* - If returning user, sign in and we are done.
* - Else check if there is an existing account with user's email.
* - If there is, return an error message.
* - Else create a new account.
*/
/**
* Sign in with Google.
*/
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
callbackURL: '/auth/google/callback',
passReqToCallback: true
}, (req, accessToken, refreshToken, profile, done) => {
if (req.user) {
User.findOne({ google: profile.id }, (err, existingUser) => {
if (err) { return done(err); }
if (existingUser) {
req.flash('errors', { msg: 'There is already a Google account that belongs to you. Sign in with that account or delete it' });
done(err);
} else {
User.findById(req.user.id, (err, user) => {
if (err) { return done(err); }
user.google = profile.id;
user.tokens.push({ kind: 'google', accessToken });
user.profile.name = user.profile.name || profile.displayName;
user.profile.gender = user.profile.gender || profile._json.gender;
user.profile.picture = user.profile.picture || profile._json.image.url;
user.save((err) => {
req.flash('info', { msg: 'Google account has been linked.' });
done(err, user);
});
});
}
});
} else {
User.findOne({ google: profile.id }, (err, existingUser) => {
if (err) { return done(err); }
if (existingUser) {
return done(null, existingUser);
}
User.findOne({ email: profile.emails[0].value }, (err, existingEmailUser) => {
if (err) { return done(err); }
if (existingEmailUser) {
req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with Google manually from Account Settings.' });
done(err);
} else {
const user = new User();
user.email = profile.emails[0].value;
user.google = profile.id;
user.tokens.push({ kind: 'google', accessToken });
user.profile.name = profile.displayName;
user.profile.gender = profile._json.gender;
user.profile.picture = profile._json.image.url;
user.save((err) => {
done(err, user);
});
}
});
});
}
}));
exports.isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/login');
};
/**
* Authorization Required middleware.
*/
exports.isAuthorized = (req, res, next) => {
const provider = req.path.split('/').slice(-1)[0];
const token = req.user.tokens.find(token => token.kind === provider);
if (token) {
next();
} else {
res.redirect(`/auth/${provider}`);
}
};
it was working before i copy paste to another directory and nothing.
SO, it was a structure problem, found and fixed.

Passport authentication for Facebook not working

I'm trying to authenticate in a node.js app using Facebook. Here's my auth route:
app.get(urls.authFbUrl, passport.authenticate('facebook', {
scope: ['email']
}));
app.get(urls.authFbCallbackUrl, passport.authenticate('facebook', {
successRedirect: urls.homeUrl,
failureRedirect: urls.authFbUrl
}));
Here is my Facebook strategy config:
passport.use(new FacebookStrategy({
clientID: configAuth.facebookAuth.clientID,
clientSecret: configAuth.facebookAuth.clientSecret,
callbackURL: configAuth.facebookAuth.callbackURL,
profileFields: ['emails', 'name']
},
function(token, refreshToken, profile, done) {
process.nextTick(function() {
console.log(token);
console.log(refreshToken);
console.log(profile);
UserModel.findOne({
'authentications.facebook.id': profile.id
}, function(err, user) {
if (err) {
return done(err);
}
if (user) {
logger.debug('User found');
return done(null, user);
} else {
var newUser = new UserModel();
newUser.authentications.facebook.id = profile.id;
newUser.authentications.facebook.token = token;
newUser.authentications.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
newUser.authentications.facebook.email = profile.emails[0].value;
newUser.email = profile.emails[0].value;
newUser.name = profile.name.givenName;
newUser.surname = profile.name.familyName;
newUser.active = true;
newUser.save(function(err) {
if (err) {
return done(err);
}
return done(null, newUser);
});
}
});
});
}));
I have verified my app secret, app ID and callback URL. Also set the app domain to localhost. Yet, upon success redirection to homepage, the user is still not authenticated, and my ACL throws 401. Any ideas why this could happen?

Categories

Resources