Reputation: 33
I'm learning to add social authentication with Facebook to an app. Everything works fine, until I actually try to login to my test app with Facebook. Instead of being routed to the profile page, I get this error:
Cannot read property '0' of undefined
TypeError: Cannot read property '0' of undefined
at Strategy.generateOrFindUser [as _verify] (C:\projects\Side Projects\passyapp\app.js:16:19)
at C:\projects\Side Projects\passyapp\node_modules\passport- oauth2\lib\strategy.js:193:24
at C:\projects\Side Projects\passyapp\node_modules\passport- github\lib\strategy.js:174:7
at passBackControl (C:\projects\Side Projects\passyapp\node_modules\oauth\lib\oauth2.js:134:9)
at IncomingMessage.<anonymous> (C:\projects\Side Projects\passyapp\node_modules\oauth\lib\oauth2.js:157:7)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
BELOW IS A SNIPPET FROM MY APP.JS FILE:
function generateOrFindUser(accessToken, refreshToken, profile, done){
if(profile.emails[0]) {
User.findOneAndUpdate(
{ email: profile.emails[0] },
{
name: profile.displayName || profile.username,
email: profile.emails[0].value,
photo: profile.photos[0].value
},
{
upsert: true
},
done
);
} else {
var noEmailError = new Error("Your email privacy settings prevent you from signing in.");
done(noEmailError, null);
}
}
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/return",
profileFields: ['email', 'id', 'displayName', 'photos']
},
generateOrFindUser)
);
//in order for passport to handle sessions you need to implement the two methods
//directly below
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(userId, done) {
User.findById(userId, function(err, done) {
//done(err, user);
});
});
This is my User Schema
var UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
trim: true,
unique: true,
},
name: {
type: String,
required: true,
trim: true,
},
favoriteBook: {
type: String,
required: false,
trim: true
},
photo: {
type: String,
required: true,
trim: true
}
});
I hope this isn't a waste of your busy coder time. Any attempt to help is greatly appreciated.
Upvotes: 1
Views: 2241
Reputation: 11
Firstly, set your profileFields
section.
'facebookAuth' : {
'clientID' : 'your App ID',
'clientSecret' : 'your App Secret',
'callbackURL' : 'your Callback URL',
'profileFields' : ['emails']
}
Now, we need to pull these details wherever we configure our passport code.
passport.use(new FacebookStrategy({
// pull in our app id and secret from our auth.js file
clientID : configAuth.facebookAuth.clientID,
clientSecret : configAuth.facebookAuth.clientSecret,
callbackURL : configAuth.facebookAuth.callbackURL,
profileFields : configAuth.facebookAuth.profileFields
}
Upvotes: 0
Reputation: 938
EDIT: better answer
I'm guessing it's the profile.emails
object (can't tell based on line number because your code is a snippet). Before that function you should have code that looks like this.
You need to ensure two things:
1.
When you call passport.authenticate
, make sure to request the email scope, like this:
app.route('/auth/facebook').get(passport.authenticate('facebook', { scope: ['email']}));
2.
passport.use(new FacebookStrategy({
clientID: facebookConfig.clientID,
clientSecret: facebookConfig.clientSecret,
callbackURL: facebookConfig.callbackURL,
profileFields : ['id', 'name', 'email'],
},
function generateOrFindUser...
It's important that your profileFields array contains email.
Upvotes: 1