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.
Related
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);
});
});
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'm trying to create an item in a mongoDB table that contains the 'picture' URL from the profile of a google user logging in to my app using passport-google-oauth20.
The following is my schema:
const userSchema = new mongoose.Schema ({
name: String,
picture: String,
googleId: String,
});
The following is the google strategy:
passport.use(new GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "https://localhost:3000/auth/google/secrets",
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
console.log(profile);
console.log(profile._json.picture);
const customerEmail = profile._json.email;
User.findOrCreate(
{ googleId: profile.id },
{ name: profile.displayName },
{ picture: profile._json.picture },
function (err, user) {
return cb(err, user);
});
}
));
in my mongo table it will create items for the 'googleId' and 'name', but will not create an item for 'picture'. and no error messages for this.
however interestingly i can console.log(profile._json.picture); and it does actually log the string (which is a URL - unsure if the fact its a URL has anything to do with this??)
Any idea what I'm doing wrong here? My assumption is that its an issue at the MongoDB side, as the URL string is being returned in the console.log.
Thanks to #Tunmee and his answer on this link.
I was not using the findOrCreate method correctly. I have change my function as follows:
function(accessToken, refreshToken, profile, cb) {
console.log(profile);
var profilePicture = profile._json.picture;
console.log(profilePicture + "inside function");
const customerEmail = profile._json.email;
User.findOrCreate(
{ googleId: profile.id, name: profile.displayName, picture: profile._json.picture },
function (err, user) {
return cb(err, user);
});
Previously the other keys and values that I wanted in my MongoDB documents were passed as the different arguments, rather than just the conditions argument.
I am trying to get the full size image from google using passport Google Oauth.
I see from other questions that the small size is coming from the "/photo.jpg?sz=50'" at the end of the url string.
since i don't think there is a way to ask for the full size on initial load, what would be the way to remove that part of the url before it gets saved to the database.
One person said to put:
iamgeUrl=user[image][url].substr(0,user[image][url].indexOf('?str=')) + '?sz=100';
but not sure where that would go in my code...
passport.use(
new GoogleStrategy(
{
// options for google strategy
clientID: process.env.googleclientID,
clientSecret: process.env.googleclientSecret,
callbackURL: "/auth/google/redirect"
},
(accessToken, refreshToken, profile, done) => {
console.log(accessToken, refreshToken, profile)
// check if user already exists in our own db
User.findOne({ googleId: profile.id }).then(currentUser => {
if (currentUser) {
// already have this user
done(null, currentUser);
} else {
// if not, create user in our db
new User({
googleId: profile.id,
username: profile.displayName,
thumbnail: profile._json.image.url,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
email: profile.emails[0].value,
})
.save()
.then(user => {
console.log("created new user: ", user);
done(null, user);
});
}
});
}
)
);
I figured it out. Just have to replace the "sz-50" with an empty string, when it gets called.
const ImgUrl = profile._json.image.url.replace("?sz=50", "")
// if not, create user in our db
new User({
googleId: profile.id,
username: profile.displayName,
thumbnail: ImgUrl,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
email: profile.emails[0].value,
})
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);
});
}