Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is function User.findOrCreate doing and when is it called in passport?

I can't find documentation on this function and therefor I can't make it work right. When is that function being called, what is it doing and what is it taking as first parameters? I'm trying to get access token from passport, but can't reach it anyhow.

passport.use(new FacebookStrategy({     clientID:   APP_ID,     clientSecret:   APP_SECRET,     callbackURL: "http://localhost:3000/",   },   function(accessToken, refreshToken, profile, done) {     User.findOrCreate({// what are these parameters?}, function (err, user) {         // when is this function called and what is it doing?         });    } )); 

How can I get access token from passport?

like image 374
Tommz Avatar asked Dec 06 '13 18:12

Tommz


People also ask

What is user findOrCreate?

User. findOrCreate is a made-up function that represents whatever function you have to find a user by Facebook ID, or to create one if the user doesn't exist.

What does done do in passport?

When success is called, it can attach the user to the request or do other things, depending on your needs (it looks for the options you pass to passport. authenticate ). If you want to determine when next will be called, you should use custom callback which gives you more flexibility.

Why should I use passport?

A passport is used to verify one's country of citizenship. If traveling outside your country, it is used to regain entry into your country of citizenship. Passports include your photo, name, birth date, gender and physical characteristics. For U.S. citizens, some countries only require a passport for re-entry.

What is passport session?

passport. session() acts as a middleware to alter the req object and change the 'user' value that is currently the session id (from the client cookie) into the true deserialized user object.


2 Answers

User.findOrCreate is a made-up function that represents whatever function you have to find a user by Facebook ID, or to create one if the user doesn't exist. I think your first problem is that your callback URL is just going to your root, so you probably are never getting to that function.

Your callback URL should be like http://localhost:3000/auth/facebook/callback.

And then handle that URL:

app.get('/auth/facebook/callback',    passport.authenticate('facebook', { failureRedirect: '/login' }),   function(req, res) {     res.redirect('/');   }); 

At this point Authentication is complete. accessToken is returned to you -- "this is needed any time the app calls an API to read, modify or write a specific person's Facebook data on their behalf". You should save this off in some table where you store access tokens for a user. profile is the other key variable because that is the info about the user (what info depends on the service).

What you do inside that function is up to you. So, make your own User.findOrCreate. Here is the code from passport for Facebook with some comments to explain it. This assumes you are using something like MongoDB and have a User table. User in this case is whatever variable you declared that can interface with the User table.

//Use facebook strategy passport.use(new FacebookStrategy({         clientID: config.facebook.clientID,         clientSecret: config.facebook.clientSecret,         callbackURL: config.facebook.callbackURL     },     function(accessToken, refreshToken, profile, done) {         //check user table for anyone with a facebook ID of profile.id         User.findOne({             'facebook.id': 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',                     //now in the future searching on 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);             }         });     } )); 

Personally I also use a "membership" table to track multiple accounts per user (so they can authenticate with multiple accounts), as I set it up through mongoose. This is actually where I store that access token. I prefer this to having a facebook column in the user table.... but that is up to you.

var mongoose = require('mongoose'),     Schema = mongoose.Schema,     ObjectId = Schema.ObjectId;  var membershipSchema = new Schema({     provider:  String,     providerUserId:  String,     accessToken: String,     userId: {type: ObjectId, ref: 'User'},     dateAdded: {type: Date, default: Date.now} });  module.exports = mongoose.model('Membership', membershipSchema); 

and as such, my version of User.findOrCreate starts off like this:

function(accessToken, refreshToken, profile, done) {     Membership.findOne({         providerUserId: profile.id     }, function(err,membershipData) {             //blah blah blah 

where membership is that model above, and is defined as a variable as:

var Membership =  require('./models/membership.js') 
like image 62
MikeSmithDev Avatar answered Oct 14 '22 11:10

MikeSmithDev


If you would like to use findOrCreate, try the npm package mongoose-findorcreate, or supergoose

e.g. mongoose-findorcreate

var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost');  var findOrCreate = require('mongoose-findorcreate') var Schema = mongoose.Schema; var UserSchema = new Schema({ facebookId: Number}); UserSchema.plugin(findOrCreate); var User = mongoose.model('User', UserSchema);  passport.use(new FacebookStrategy({         clientID: 'clientID',         clientSecret: 'clientSecret',         callbackURL: "/auth/facebook/callback"     },     function(accessToken, refreshToken, profile, cb) {         User.findOrCreate({ facebookId: profile.id }, function (err, user) {           console.log('A new uxer from "%s" was inserted', user.facebookId);           return cb(err, user);         });     } )); 
like image 29
Vinnie James Avatar answered Oct 14 '22 11:10

Vinnie James