Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs Passport - Using Multiple Google Strategies

I am not sure if this is possible but I would like to use multiple Google strategies in order to use a different set of scopes depending on the link/user.

I have created two separate passport variables:

 passport = require('passport')
 passport2 = require('passport')

I have setup them both as follows:

passport.use(new GoogleStrategy({
    clientID: GOOGLE_CLIENT_ID,
    clientSecret: GOOGLE_CLIENT_SECRET,
    callbackURL: "http://localhost:3000/auth/callback"
},
  function(accessToken, refreshToken, profile, done) {
    // asynchronous verification, for effect...                                                                    
    process.nextTick(function (){

      // Changing this to return the accessToken instead of the profile information                                
        console.log(profile.displayName);                                                                        

      return done(null, [{token:accessToken,rToken:refreshToken,'profile':profile}]);
    });
  }
));


passport2.use(new GoogleStrategy({
    clientID: GOOGLE_CLIENT_ID,
    clientSecret: GOOGLE_CLIENT_SECRET,
    callbackURL: "http://localhost:3000/join/callback"
  },
  function(accessToken, refreshToken, profile, done) {
    // asynchronous verification, for effect...                                                                    
    process.nextTick(function (){

      // Changing this to return the accessToken instead of the profile information                                
        //console.log(profile);                                                                        

      return done(null, [{token:accessToken,rToken:refreshToken,'profile':profile}]);
    });
  }
))

For my routes I have this:

app.get('/auth',
passport.authenticate('google', {scope: ['scopes'],
                                 accessType:'offline', approvalPrompt:'force'})
);

app.get('/joinreq',
    passport2.authenticate('google', {scope: ['different_scopes]})
);

And my callbacks look like this:

app.get('/join/callback', function(req,res){
    console.log('made it to the join callback');
    res.redirect('/great')

}

app.get('/auth/callback', function(req,res){
    console.log('made it to the auth callback');
    res.redirect('/index')
}

I am able to successfully authenticate with each scope successfully - the problem I'm running into is that my callback is only going to the /join/callback. It seems like the variable passport2 is overwriting the value of passport.

Is there any way I can get around this? I want a set of scopes for admin users and a set of scopes for everyone else.

like image 313
MonsterWimp757 Avatar asked Nov 06 '14 18:11

MonsterWimp757


2 Answers

A slightly cleaner way is to set up separate auth points with separate names, rather than overwriting the registered strategy on each request. By default, passport gives GoogleStrategy the name "google", but you can specify a different name as the first argument to install a second strategy.

// set up first Google strategy
passport.use('google', new GoogleStrategy({
    clientID: GOOGLE_CLIENT_ID,
    clientSecret: GOOGLE_CLIENT_SECRET,
    callbackURL: "http://localhost:3000/join/callback"
  }, function(accessToken, refreshToken, profile, done) {
    ...
  }
)

// Second strategy -- could use different callback URL, etc.
passport.use('google-alt', new GoogleStrategy({
    ...
});

app.get('/auth', passport.authenticate('google', ['scopes']))
app.get('/joinauth', passport.authenticate('google-alt', ['scopes']))
like image 82
user85461 Avatar answered Sep 18 '22 02:09

user85461


This was solved by creating two middleware functions to define the passport variable depending on the route:

app.get('/auth',middlefunc,passport.authenticate('google',['scopes']))
app.get('/joinauth',middlefunc2,passport.authenticate('google',['scopes']))


function middlefunc(req,res,next){
    passport.use(new GoogleStrategy({
    clientID: GOOGLE_CLIENT_ID,
    clientSecret: GOOGLE_CLIENT_SECRET,
    callbackURL: "http://localhost:3000/join/callback"
  },
  function(accessToken, refreshToken, profile, done) {
    // asynchronous verification, for effect...                                                                    
    process.nextTick(function (){

      // Changing this to return the accessToken instead of the profile information                                
        //console.log(profile);                                                                        

      return done(null, [{token:accessToken,rToken:refreshToken,'profile':profile}]);
    });
  }
))
    }

function middlefunc2(req,res,next){
    //another definition of passport.use

}

There was no need to make another passport variable.

like image 40
MonsterWimp757 Avatar answered Sep 21 '22 02:09

MonsterWimp757