Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 849
SebastianG Avatar asked Jun 08 '20 17:06

SebastianG


2 Answers

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() {}
like image 121
Akashii Avatar answered Oct 11 '22 09:10

Akashii


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
    })
);
like image 4
cpuchip Avatar answered Oct 11 '22 08:10

cpuchip