1

What am I missing here? I've been through all the threads here and googled it for a while:

  • Whitelisted my machine's IP under the apps advanced settings.
  • Double-checked the token and when it's expired I can see that error on the console.
  • Double checked client + secret + origins in the app
  • Tried things with a google oauth token and I get 'unauthorized' as intended.

But when all is good and I send a request with that good token either from Postman or from my frontend I get Internal Server Error telling me User is not defined at that line. What am I missing?

Route code:

app.get(
  '/user',
  passport.authenticate('facebook-token', { session: false }),
  function(req, res) {
    res.send('SUCCESS');
  }
);

All other code without imports:

app.use(cors());
app.use(express.json());
app.use(helmet());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(passport.initialize());
passport.use(
  new FacebookTokenStrategy(
    {
      clientID: config.get('facebook.clientID'),
      clientSecret: config.get('facebook.clientSecret')
    },
    function(accessToken, refreshToken, profile, done) {
      User.findOrCreate({ facebookId: profile.id }, function(error, user) {
        return done(error, user);
      });
    }
  )
);

and I'm importing the npm package exactly as in the docs:

const FacebookTokenStrategy = require('passport-facebook-token');

I'm all out of ideas on this one.

SebastianG
  • 8,563
  • 8
  • 47
  • 111
  • 1
    Do you have a findorCreate method defined on user model? – cEeNiKc Mar 15 '19 at 09:55
  • I don't even have a user model in this instance. I'm not trying to authenticate users but rather authorize them to go through a route. I'm using the 'passport-facebook-token' npm package not the 'passport-facebook'. I've worked heavily in the past with ADAL and the flow was quite different than this which makes it so much more confusing. – SebastianG Mar 15 '19 at 09:59
  • 1
    See if you don’t have a user model you can’t call User.findorCreate. After getting profile just call done(null, profile) instead of user. That’s just pseudo code defined in passport docs which says you either find an existing user or create a new one in the database but if you are not using a database in this case you don’t have to do that. – cEeNiKc Mar 15 '19 at 10:01
  • @cEeNiKc I will be using one but I thought I'll handle that implementation once I'm all good & done with testing out this part. I will have a middleware where I look into my own sql DB for a user email and if there isn't one I'll create it. I'll go ahead and test it out with your modifications. – SebastianG Mar 15 '19 at 10:04

1 Answers1

2
app.use(cors());
app.use(express.json());
app.use(helmet());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(passport.initialize());
passport.use(
  new FacebookTokenStrategy(
    {
      clientID: config.get('facebook.clientID'),
      clientSecret: config.get('facebook.clientSecret')
    },
    function(accessToken, refreshToken, profile, done) {
      return done(null, profile);
    }
  )
);

Try this

cEeNiKc
  • 1,308
  • 7
  • 13
  • 1
    Great. Now whenever you will be integrating your sql db, you’ll have to check for the existing user or create a new one in this function only and then call done with that user. – cEeNiKc Mar 15 '19 at 10:09
  • Hmm -- this is just a personal architecture curiosity question -- do you think it would be better performance-wise in that function right there to check against an array of users stored in memory VS calling the database every time? would that be a common pattern/use case? – SebastianG Mar 15 '19 at 10:13
  • 1
    Basically, you get the profile id from any third party in this case facebook in this function. Now, you check in your database based on this id whether a user already exists otherwise you create a new one. If you want, you can do this in a separate function which you will have to call after you authenticate, but you will have to pass another unnecessary middleware and do the same thing there. So convention is to do all in this function and return the existing or new user which you can access in later middlewares. – cEeNiKc Mar 15 '19 at 10:17
  • 1
    And for the memory vs database question, are you storing all users info in memory also? Convention is to store only session of users logged in in the memory. – cEeNiKc Mar 15 '19 at 10:18
  • I haven't really made up my mind yet but I guess it will depend on the number of users + database speed. Right now I'm thinking I'll just do it via database call and see the kind of performance I'm getting and maybe try to cache the list later on so it doesn't take too much checking if a user exists or not and have some logic to update the cache to all backend instances. Thanks very much for your time and help! – SebastianG Mar 15 '19 at 10:23