Using passport-google-oauth20, trying to create item mongo for picture URL - node.js

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.

Related

MongoError: E11000 duplicate key error collection when trying to Log In

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 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.

Make the google profile image larger size from Google Oauth using passport

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,
})

Passport strategy for authenticating with LinkedIn using the OAuth 2.0a API return undefined email on save User

Unable to retrieve the user email on LinkedIn. I have used passport-LinkedIn and OAuth 2.0. I can interpolate the username and picture. This is the code that I have tried.
var LinkedIn = require('passport-linkedin-oauth2').Strategy;
module.exports = (passport, User) => {
passport.use( new LinkedIn({
clientID: '86ew637ipvirsa',
clientSecret: 'HoEMfqCBGL9SxsIt',
callbackURL: 'http://localhost:3000/auth/linkedin/callback'
}, (accesstoken, refreshToken, profile, done) => {
User.findOne({'linkedin.id': profile.id}, (err, x) => {
if (x) return done(null, x);
var user = {
displayName: profile.displayName,
image: profile._json.pictureUrl,
email: profile.emailAddress,
linkedin: {
id: profile.id
}
};
User.create(user);
User.create(user, (err, x) => done(null, x));
});
}));
};
the npm package being used by you is not properly documented. The author has not explicitly said how you can access the email field from the profile variable.
You can pass in the scope with strategy and get the email fields by logging the profile variable.
passport.use(new LinkedInStrategy({
clientID: LINKEDIN_KEY,
clientSecret: LINKEDIN_SECRET,
callbackURL: "http://127.0.0.1:3000/auth/linkedin/callback",
scope: ['r_emailaddress', 'r_basicprofile'], //pass the scope
state: true
}, function(accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
console.log(profile); //logging
return done(null, profile);
});
}));
You can also use another package . Here you can explicitly define the profile fields you want to access.

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