MongoError: E11000 duplicate key error collection when trying to Log In - node.js

I logged in with google in my app without problems, I logged out and when logged in again I got this error:
"MongoError: E11000 duplicate key error collection: myAppDB.users index: username_1 dup key: { username: "John Doe" }"
I'm not creating a new user with the same name, I'd just need to log in.
App.js
mongoose.set("useCreateIndex", true);
const userSchema = new mongoose.Schema({
googleId: String,
profileImage: String,
myCollection: {
type: Object,
default: Object
},
games: {
type: Object,
default: Object
}
});
userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);
const User = new mongoose.model("User", userSchema);
passport.use(new GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/myApp",
userProfileUrl: "https://www.googleapis.com/oauth2/v3/userinfo",
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, cb) {
console.log(profile);
User.findOrCreate({
googleId: profile.id,
username: profile.displayName,
profileImage: profile.photos[0].value,
myCollection: catalogDb,
games: {}
},
function(err, user) {
return cb(err, user);
});
}
));
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);
});
});

Related

ValidatorError: Path `lastName` is required

I'm new at Node.js and really a newbie at MongoDB.
I'm trying to make an authentication system using Google OAuth 2.0 and passport.
I keep getting this error:
Error: User validation failed: lastName: Path `lastName` is required.
Can you help me? I got this code from GitHub and I'm trying to modify it, but this error doesn't let me continue my project.
This is the problematic code:
const mongoose = require('mongoose')
const User = require('../models/User')
module.exports = function (passport) {
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback',
},
async (accessToken, refreshToken, profile, done) => {
const newUser = {
googleId: profile.id,
displayName: profile.displayName,
firstName: profile.name.givenName,
lastName: 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, user)
}
} catch (err) {
console.error(err)
}
}
)
)
passport.serializeUser((user, done) => {
done(null, user.id)
})
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => done(err, user))
})
}

I am not able to insert facebook account to mongodb

I am trying to sign up my users using facebook using passportjs. I am using mongodb as database and using mongoose to interact with it.
const userSchema = mongoose.Schema({
email: String,
password: String,
googleId: String,
facebookId: String,
secret: [String],
});
const User = mongoose.model("users", userSchema);
This is the schema.
passport.use(new FacebookStrategy({
clientID: process.env.APP_ID,
clientSecret: process.env.APP_SECRET,
callbackURL: process.env.CALLBACK_URL,
profileFields: ['id', 'displayName', 'photos', 'email']
},
function (accessToken, refreshToken, profile, done) {
//check user table for anyone with a facebook ID of profile.id
console.log(profile);
User.findOne({
facebookId: profile.id
}, function (err, user) {
if (err) {
return done(err);
}
//No user was found... so create a new user with values from Facebook (all the profile. stuff)
if (!user) {
user = new User({
name: profile.displayName,
email: profile.emails[0].value,
username: profile.username,
provider: 'facebook',
User.findOne({'facebook.id': profile.id } will match because of this next line
facebook: profile._json
});
user.save(function (err) {
if (err) console.log(err);
return done(err, user);
});
} else {
//found user. Return
return done(err, user);
}
});
}
));
This is the code of facebook strategy. I can sign up succesfully using facebook but I am not able to add the user to my database. I have the same code for my google oauth and it seems to work in google.

Mongoose Save Error LinkedIn Data

Im using Passport-LinkedIn for auth and getting some user data but Passport-LinkedIn returns to some defined datas like email, Formatted Name(firstname + Surname) etc and an JSON Data what you defines in Strategy, I defined like this:
profileFields: [
'id',
'headline',
'summary',
'first-name',
'last-name',
'email-address',
'public-profile-url',
'picture-urls::(original)',
'industry']
}
I defined Function Like This:
//PassportJs - LinkedIn
passport.use(new linkedInStrategy({
consumerKey: config.consumerKey,
consumerSecret: config.consumerSecret,
callbackURL: config.callbackURL,
scope: config.scope,
profileFields: config.profileFields
},
function(token, tokenSecret, profile, done) {
User.findOne({
linkedinId: profile.id
}, (err, user)=>{
if(err){
return done(err);
}
//No user was found, Create new
if(!user){
//Logs
console.log(profile);
user = new User({
linkedinId: profile.id,
firstName: profile._json.firstName,
lastName: profile._json.lastName,
formattedName: profile.displayName,
email: profile.emails[0].value,
linkedinUrl: profile._json.publicProfileUrl,
industry: profile._json.industry,
summary: profile._json.summary,
profileImage: profile._json.pictureUrl.value[0],
headline: profile._json.headline
});
user.save((err)=>{
if (err) console.log(err);
return done(err, user); // If !error return User and Save
});
} else{
//found user. return
console.log(profile);
return done(err, user);
}
});
}
));
But if User has no Profile Image or missing fields in defined data thats give me error like :
events.js:183
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property 'value' of undefined
at User.findOne (/home/berkay-ubuntu/Projects/ecosystem-mail/auth/linkedin.js:51:58)
at /home/berkay-ubuntu/Projects/ecosystem-mail/node_modules/mongoose/lib/model.js:4467:16
at model.Query.Query._completeOne (/home/berkay-ubuntu/Projects/ecosystem-mail/node_modules/mongoose/lib/query.js:1704:12)
at Immediate.Query.base.findOne.call (/home/berkay-ubuntu/Projects/ecosystem-mail/node_modules/mongoose/lib/query.js:1764:10)
at Immediate._onImmediate (/home/berkay-ubuntu/Projects/ecosystem-mail/node_modules/mquery/lib/utils.js:119:16)
at runCallback (timers.js:794:20)
at tryOnImmediate (timers.js:752:5)
at processImmediate [as _immediateCallback] (timers.js:729:5)
I want to defines 'null' if there is a missing data
Thank you!
I Found a solution later like this:
//PassportJs - LinkedIn
passport.use(new linkedInStrategy({
consumerKey: config.consumerKey,
consumerSecret: config.consumerSecret,
callbackURL: config.callbackURL,
scope: config.scope,
profileFields: config.profileFields
},
function(token, tokenSecret, profile, done) {
User.findOne({
linkedinId: profile.id
}, (err, user)=>{
if(err){
return done(err);
}
//No user was found, Create new
if(!user){
//Logs
console.log(profile);
// console.log(profileImage);
profileImage = null;
if (!profile._json.pictureUrls){
console.log('Undefined');
console.log(this.profileImage);
}else{
console.log('Defined');
this.profileImage = profile._json.pictureUrls.values[0];
console.log(this.profileImage);
}
user = new User({
linkedinId: profile.id,
firstName: profile._json.firstName,
lastName: profile._json.lastName,
formattedName: profile.displayName,
email: profile.emails[0].value,
linkedinUrl: profile._json.publicProfileUrl,
industry: profile._json.industry,
summary: profile._json.summary,
profileImage: this.profileImage,
headline: profile._json.headline
});
user.save((err)=>{
if (err) console.log(err);
return done(err, user); // If !error return User and Save
});
} else{
//found user. return
console.log(profile);
return done(err, user);
}
});
}
));

Can't use facebook to login because user model setting in local passport

I am trying to build a login system with Facebook, Google and local passport, I am using Node.js, passport.js, and ORM to finish it, but I faced one problem now, my user model is like below
const User = connection.define('user', { googleID: {
type: Sequelize.STRING, }, facebookID: {
type: Sequelize.STRING, }, firstname: {
type: Sequelize.STRING,
notEmpty: true,
},
lastname: {
type: Sequelize.STRING,
notEmpty: true,
},
username: {
type: Sequelize.TEXT,
},
email: {
type: Sequelize.STRING,
validate: {
isEmail: true,
},
},
password: {
type: Sequelize.STRING,
allowNull: false,
},
last_login: {
type: Sequelize.DATE,
}, });
After this setting, whenever I want to log on my website through Facebook, it kept showing SEQUELIZE ERROR, password required! I know it the reason is I don't have password while signing in with Facebook, but what can I do with this issue? I saw this page on GitHub https://github.com/feathersjs/authentication/issues/168
but I still have no clue in using this feathers-joi tool, can anyone give me some advice? Thank you
Here is my Facebook.js code
const passport = require('passport');
const cookieSession = require('cookie-session');
const FacebookStrategy = require('passport-facebook').Strategy;
const User = require('../models/User');
const keys = require('../secret/keys.js');
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id).then(user => {
done(null, user);
});
});
passport.use(new FacebookStrategy({
clientID: keys.facebookClientID,
clientSecret: keys.facebookClientSecret,
callbackURL: '/auth/facebook/callback',
}, (accessToken, refreshToken, profile, done) => {
User.findOne({ where: { facebookID: profile.id } }).then(existinguser => {
if (existinguser) {
//Nothing will happen, the ID already exists
done(null, existinguser);
}else {
User.create({ facebookID: profile.id }).then(user => done(null, user));
}
});
}));
My passport.js would be like below(Still need some fix)
var bCrypt = require('bcrypt-nodejs');
module.exports = function(passport, user) {
var User = user;
var LocalStrategy = require('passport-local').Strategy;
passport.use('local-signup', new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) {
var generateHash = function(password) {
return bCrypt.hashSync(password, bCrypt.genSaltSync(8), null);
};
User.findOne({
where: {
email: email
}
}).then(function(user) {
if (user)
{
return done(null, false, {
message: 'That email is already taken'
});
} else
{
var userPassword = generateHash(password);
var data =
{
email: email,
password: userPassword,
firstname: req.body.firstname,
lastname: req.body.lastname
};
User.create(data).then(function(newUser, created) {
if (!newUser) {
return done(null, false);
}
if (newUser) {
return done(null, newUser);
}
});
}
});
}
));
}
try this
passport.use(new FacebookStrategy({
clientID: keys.facebookClientID,
clientSecret: keys.facebookClientSecret,
callbackURL: '/auth/facebook/callback',
}, (accessToken, refreshToken, profile, done) => {
User.findOne({ where: { facebookID: profile.id } }).then(existinguser => {
if (existinguser) {
//Nothing will happen, the ID already exists
done(null, existinguser);
}else {
var object = {
facebookID: profile.id,
password: ""
}
User.create(object).then(user => done(null, user));
}
});
}));

Passport-Facebook giving two different facebook Id

I tried to implement facebook OAUTH for my applications(Web and Mobile) using Sails.js/Node.js and Mongo as my backend. I wrote a dedicated function to access the endpoints for each app cause the webApp needs a callback URL and the mobile doesn't. My code screenshot is available below. But, I noticed the two gives me two different Facebook id. I am confused, shouldn't the facebookId be unique? I am using these two modules
FacebookStrategy = require('passport-facebook').Strategy
FacebookTokenStrategy = require('passport-facebook-token').Strategy
WebApp Strategy
passport.use(new FacebookStrategy({
clientID : facebook.clientID,
clientSecret : facebook.clientSecret,
profileFields : ['id', 'email', 'last_name', 'first_name', 'gender', 'link', 'verified', 'updated_time', 'timezone', 'age_range'],
passReqToCallback: true
},
function(req, accessToken, refreshToken, profile, done) {
authenticate(req, accessToken, refreshToken, profile, done);
}
));
The authenticate function being pointed at
var authenticate = function (accessToken, refreshToken, profile, done) {
User.findOne({facebookId: profile.id}).then(function (user){
if (user) {
return [user, {accessToken: accessToken, refreshToken: refreshToken}]
} else {
var data = {
facebookId: profile.id,
firstname: profile._json.first_name,
lastname: profile._json.last_name,
email: profile._json.email,
gender: profile._json.gender,
fb_profile_url: profile._json.link,
fb_verified: profile._json.verified,
fb_updated_time: profile._json.updated_time,
phonenumber: profile._json.phone
}
var userQry = User.create(data);
}
return [userQry, {accessToken: accessToken, refreshToken: refreshToken}]
})
.spread(function (user, credentials){
if (user) {
return done(null, [user, credentials]);
} else {
return done(null, null);
}
})
.catch(function (err){
return done(err, null);
});
}

Resources