2

I would like to take a user provided username on my React client side and pass it into Google Oauth on my server side during the authentication flow. I originally thought I would pass it in with req.params.username by simply calling /api/auth/google/${username} and saving it to my mongo database with req.update() or attaching it to the profile object google returns via profile.username = req.params.username. Unfortunately, I'm not familiar enough with how the Google strategy works as middleware.

Currently, a user signs up by being sent to /api/auth/google, and then the Google strategy takes care of the flow automatically.

    app.get('/auth/google', passport.authenticate('google', {
        scope: ['profile', 'email']
      }))

My Google strategy is as follows:

    passport.use(new GoogleStrategy(
      {
      clientID: keys.googleClientID,
      clientSecret: keys.googleClientSecret,
      callbackURL: "/auth/google/callback",
      proxy: true
    }, 
    async (accessToken, refreshToken, profile, done) => {
      const existingUser = await User.findOne({ googleId: profile.id, 
    image: profile.photos[0].value})

      if (existingUser){
        return done(null, existingUser);
      } 

      const newUser = new User({ googleId: profile.id, image: 
    profile.photos[0].value}).save();  
      done(null, newUser);    
      })
    );

and the callback route:

    app.get('/auth/google/callback', passport.authenticate('google'), 
       (req, res) => {
         res.redirect('/')
       })

Since the user profile returned is saved to the mongo db inside the Google strategy itself, I'm not sure how to attach the req.params.username to the profile object. Any suggestions on how to access the username inside the Google strategy before I do the newUser = ().save() command? Or is there a better way to attach a username to the saved user?

Julian
  • 23
  • 3

1 Answers1

2

Your original idea was spot-on; you were just missing one implementation detail. OAuth2 strategies, like the GoogleStrategy you're using here, can be passed a {passReqToCallback: true} flag in the strategy config options. When this is set, your callback will have access to the original request:

passport.use(new GoogleStrategy({
  clientID: keys.googleClientID,
  clientSecret: keys.googleClientSecret,
  callbackURL: "/auth/google/callback",
  proxy: true,
  passReqToCallback: true
}, 
async (req, accessToken, refreshToken, profile, done) => {
  // Now you have access to the original req.params.username, or any data
  // the original request has attached to it
  ...
})

See also:

Using PassportJS, how does one pass additional form fields to the local authentication strategy?

Get request object in Passport strategy callback

Andy Taton
  • 491
  • 4
  • 8
  • This is exactly what I was looking for, thank you so much for taking the time to help me out Andy. – Julian Aug 12 '18 at 06:39