Passport Google Oauth2 not prompting select account when only 1 google account logged in
Asked Answered
G

3

11

I'm trying to authenticate users in my node + nestjs api and want to prompt the user to select an account.

The prompt does not show up if you have only 1 account logged in and even when you are logged in with 2 accounts and you get prompted, the URL in the redirect still has &prompt=none in the parameters.

I can in fact confirm that it makes no difference that prompt option.

My code simplified below:

import { OAuth2Strategy } from "passport-google-oauth";
import { PassportStrategy } from "@nestjs/passport";
@Injectable()
export class GoogleStrategy extends PassportStrategy(OAuth2Strategy, "google") {
  constructor(secretsService: SecretsService) {
    super({
      clientID: secretsService.get("google", "clientid"),
      clientSecret: secretsService.get("google", "clientsecret"),
      callbackURL: "https://localhost:3000/auth/google/redirect",
      scope: ["email", "profile", "openid"],
      passReqToCallback: true,
      prompt: "select_account",
    });
  }

  async validate(req: Request, accessToken, refreshToken, profile, done) {
    const { name, emails, photos } = profile;
    const user = {
      email: emails[0].value,
      firstName: name.givenName,
      lastName: name.familyName,
      picture: photos[0].value,
      accessToken,
    };
    return done(null, user);
  }
}

How can i possibly further debug this to see why/whats happening under the hood?

The actual endpoints:


@Controller("auth")
export class AuthController {
  @Get("google")
  @UseGuards(AuthGuard("google"))
  private googleAuth() {}

  @Get("google/redirect")
  @UseGuards(AuthGuard("google"))
  googleAuthRedirect(@Req() req: Request, @Res() res: Response) {
    if (!req.user) {
      return res.send("No user from google");
    }

    return res.send({
      message: "User information from google",
      user: req.user,
    });
  }
}

I can't pass an options object with any of the guards or UseGuards decorator.

I've also tried to pass an extra object parameter to the super call but that didn't work either.

Godwit answered 8/6, 2020 at 17:51 Comment(0)
C
9

Sebastian I've been dealing with this issue as well for about a week. I've finally found what the issue was, and then found that there's a very similar Stack Overflow article that had the same problem:

Auto login while using passport-google-oauth20

The problem comes in when you initialize OAuth2Strategy class with options. It does not pass it's options along to the passport.authenticate(passport, name, options, callback) call since passport.authenticate(...) is only called when you register your middleware handlers for your routes.

You therefore need to pass prompt: 'select_account' when you register passport.authenticate() route middleware

Like so:

router.get(
    '/auth/google',
    passport.authenticate('google', {
        accessType: 'offline',
        callbackURL: callbackUrl,
        includeGrantedScopes: true,
        scope: ['profile', 'email'],
        prompt: 'select_account', // <=== Add your prompt setting here
    })
);
Canaletto answered 22/7, 2020 at 21:7 Comment(0)
A
8

For anyone use nestjs and facing same issue, here is the solution

    class AuthGoogle extends AuthGuard('google') {
        constructor() {
            super({
                prompt: 'select_account'
            });
        } }
    }
     // using
    @UseGuards(AuthGoogle)
    private googleAuth() {}
Asphyxiate answered 16/10, 2020 at 4:4 Comment(1)
That's great, it's work, can you explain for me why I need to define a new class AuthGoogle, pleaseNarda
P
1

Sebastian, you can also do this straight from the strategy class itself instead of making a guard specially for invoking the prompt.

Check below.

sample code

Just add this after your constructor call in the strategy class and it will work. You can directly copy the code.

Preordain answered 20/9, 2022 at 9:26 Comment(1)
Post the code in your answer, don't just link to it :)Diffuser

© 2022 - 2024 — McMap. All rights reserved.