mcktimo
mcktimo

Reputation: 1460

How to pass an additional parameter to passport.authenticate

(I already do fbStrategy.passReqToCallback = true ) I am riffing off https://scotch.io/tutorials/easy-node-authentication-linking-all-accounts-together but want to use this social authentication service for multiple apps, ex: the one that controls the heating system, the one that turns on the sprinklers etc.

Basically if one of these apps checks with the server and doesn't have a correct token it get redirected to this social authentication service (social-auth). When the user presses on of the social login buttons it grabs the parameter of what app its arriving from and adds it as a parameter for /auth/facebook/:appid

    // send to facebook to do the authentication
    app.get('/auth/facebook/:appId', function(req,res,next){
        passport.authenticate(
            'facebook', { scope : 'email' }
        )(req,res,next);
    });

req of req,res,next is the serialized user record. At this point social-auth doesn't know who the user is.

fbStrategy.passReqToCallback = true;  
passport.use(new FacebookStrategy(fbStrategy,
    function(req, token, refreshToken, profile, done) {
        var email = (profile.emails[0].value || '').toLowerCase()     
        process.nextTick(function() {...

Once authorization is complete I want to redirect back to the calling app and I need the :appId param to ride along so I can go back to the right site.

Now generally it would work if I just made a variable like currentAppId accessible to the various social stategies but If you happened to have multiple people authenticating at the same time then you conceivably have a user return to the wrong app, or some other users app. That's why I need appId to travel as param to passport.authenticate . Where should I be looking to figure out how. Could I wrap passport.authenticate or otherwise modify things?

Upvotes: 21

Views: 21422

Answers (2)

davidrl1000
davidrl1000

Reputation: 361

In my case, due to the authentication flow, to set up a variable in req was not working.

The second option, set passReqToCallBack: true was giving me many issues, so it was not an option either. More information can be found here.

The solution came to me following the answer that Dhiraj posted in thread above, I did set a single string in the state and I was able to use the string on the callbacks.

login: (req, res, next) => passport.authenticate('google', {
    scope: ['profile', 'email'],
    state: req.query.username
  }, () => next())(req, res, next),

  onSuccess: async(req, res) => {
    console.log(req.query.state)
  },

Upvotes: 2

Manfred Steiner
Manfred Steiner

Reputation: 1295

You can use the request itself to transfer some additional parameters from and to the strategy function. In the following example the two parameters _toParam and _fromParam are used for this concern.

app.get('/auth/facebook/:appId', function(req,res,next){
    req._toParam = 'Hello';
    passport.authenticate(
        'facebook', { scope : 'email' }
    )(req,res,next);
})


fbStrategy.passReqToCallback = true;  
passport.use(new FacebookStrategy(fbStrategy,
    function(req, token, refreshToken, profile, done) {
        console.log(req._toParam);
        req._fromParam = 'Hello 2';
        var email = (profile.emails[0].value || '').toLowerCase()     
    process.nextTick(function() {...

If you need to store the id for further requests, you could use a map with the socket of the current request as key.

Upvotes: 22

Related Questions