Get request object in Passport strategy callback
Asked Answered
A

3

48

So here is my configuration for passport-facebook strategy:

    passport.use(new FacebookStrategy({
        clientID: ".....",
        clientSecret: ".....",
        callbackURL: "http://localhost:1337/register/facebook/callback",
    },
    facebookVerificationHandler
    ));

And here is facebookVerificationHandler:

var facebookVerificationHandler = function (accessToken, refreshToken, profile, done) { 
    process.nextTick(function () {    
        .......
    });    
};

Is there a way to access to the request object in facebookVerificationHandler?

Users are registered to my site with a LocalStrategy but then they will be able to add their social accounts and associate those account with their local accounts. When the callback above is called, the user who is currently logged in is already available in req.user so I need to access req to associate the user with the facebook account.

Is this the correct way to implement it or should I consider another way of doing it?

Thanks.

Airlee answered 2/12, 2013 at 23:57 Comment(0)
S
16

For this reason instead of setting up the strategy when the application starts I usually setup the strategy when there is a request. for instance:

app.get(
    '/facebook/login'
    ,passport_setup_strategy()
    ,passport.authenticate()
    ,redirect_home()
);

var isStrategySetup = false;
var passport_setup_strategy = function(){
    return function(req, res, next){
        if(!isStrategySetup){

            passport.use(new FacebookStrategy({
                    clientID: ".....",
                    clientSecret: ".....",
                    callbackURL: "http://localhost:1337/register/facebook/callback",
                },
                function (accessToken, refreshToken, profile, done) { 
                    process.nextTick(function () {    
                        // here you can access 'req'
                        .......
                    });    
                }
            ));

            isStrategySetup = true;

        }

        next();
    };
}

Using this you will have access to the request in your verification handler.

Spinner answered 3/12, 2013 at 2:41 Comment(3)
Also see: #11784733Spinner
Does passport replace its old FacebookStrategy with this new FacebookStrategy?Thyestes
This was a useful solution to me because I wanted to use req.protocol and req.get('host') in generating the callbackURL parameterPoachy
C
97

There's a passReqToCallback option, see the bottom of this page for details: http://passportjs.org/guide/authorize/

Chuch answered 4/12, 2013 at 5:21 Comment(1)
Works well to get the request object to the strategy function, but I've not been able to use it in the database callback (in my case it's nano with CouchDB). Except for the callback all information is lost. Do you have any idea on how to get the request object through to these as well?Pandurate
O
20

Try this.

exports.facebookStrategy = new FacebookStrategy({
        clientID: '.....',
        clientSecret: '...',
        callbackURL: 'http://localhost:3000/auth/facebook/callback',
        passReqToCallback: true
    },function(req,accessToken,refreshToken,profile,done){
        User.findOne({
                'facebook.id' : profile.id
            },function(err,user){
            if(err){
                done(err);
            }
            if(user){
                req.login(user,function(err){
                    if(err){
                        return next(err);
                    }
                    return done(null,user);
                });
            }else{
                var newUser = new User();
                newUser.facebook.id = profile.id;
                newUser.facebook.name = profile.displayName;
                newUser.facebook.token = profile.token;
                newUser.save(function(err){
                    if(err){
                        throw(err);
                    }
                    req.login(newUser,function(err){
                        if(err){
                            return next(err);
                        }
                        return done(null,newUser);
                    });
                });
            }
        });
    }
);

User is a mongoose model, i save the user in DB.

Opponent answered 1/2, 2015 at 1:8 Comment(3)
Best solution (because I don't have to refactor to create FbStratey on every request), thanks! I think this should be marked as the correct answer. The main code that answers the question - How to actually support getting the 'req' param in the handler function - is this section here, add the 4th JSON param and then see that you can have the 'req' param now in function signature: .... passReqToCallback: true },function(req,accessToken,refreshToken,profile,done){Columbuscolumbyne
Thanks, i am happy that you found it useful.Opponent
req.login and done(null, newUser) is redundant. done(null, newUser) logs the user in.Chaffer
S
16

For this reason instead of setting up the strategy when the application starts I usually setup the strategy when there is a request. for instance:

app.get(
    '/facebook/login'
    ,passport_setup_strategy()
    ,passport.authenticate()
    ,redirect_home()
);

var isStrategySetup = false;
var passport_setup_strategy = function(){
    return function(req, res, next){
        if(!isStrategySetup){

            passport.use(new FacebookStrategy({
                    clientID: ".....",
                    clientSecret: ".....",
                    callbackURL: "http://localhost:1337/register/facebook/callback",
                },
                function (accessToken, refreshToken, profile, done) { 
                    process.nextTick(function () {    
                        // here you can access 'req'
                        .......
                    });    
                }
            ));

            isStrategySetup = true;

        }

        next();
    };
}

Using this you will have access to the request in your verification handler.

Spinner answered 3/12, 2013 at 2:41 Comment(3)
Also see: #11784733Spinner
Does passport replace its old FacebookStrategy with this new FacebookStrategy?Thyestes
This was a useful solution to me because I wanted to use req.protocol and req.get('host') in generating the callbackURL parameterPoachy

© 2022 - 2024 — McMap. All rights reserved.