护照谷歌Oauth2不提示选择帐户时只有1个谷歌帐户登录



我正在尝试在我的节点 + nestjs api 中对用户进行身份验证,并希望提示用户选择一个帐户。

如果您只登录了 1 个帐户,则不会显示提示,即使您使用 2 个帐户登录并收到提示,重定向中的 URL 在参数中仍然包含 &prompt=none。

事实上,我可以确认提示选项没有区别。

我的代码简化如下:

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);
}
}

我怎样才能进一步调试它以查看引擎盖下发生的原因/内容?

实际端点:


@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,
});
}
}

我不能使用任何守卫或 UseGuards 装饰器传递选项对象。

我还尝试将一个额外的对象参数传递给超级调用,但这也没有用。

塞巴斯蒂安 我也一直在处理这个问题大约一个星期。我终于找到了问题所在,然后发现有一篇非常相似的 Stack Overflow 文章有同样的问题:

使用护照时自动登录-谷歌-oauth20

当您使用选项初始化类时OAuth2Strategy问题就出现了。它不会将其选项传递给passport.authenticate(passport, name, options, callback)调用,因为仅在为路由注册中间件处理程序时调用passport.authenticate(...)

因此,在注册路由中间件时需要传递prompt: 'select_account'passport.authenticate()

这样:

router.get(
'/auth/google',
passport.authenticate('google', {
accessType: 'offline',
callbackURL: callbackUrl,
includeGrantedScopes: true,
scope: ['profile', 'email'],
prompt: 'select_account', // <=== Add your prompt setting here
})
);

对于任何使用 nestjs 并面临相同问题的人,这里是解决方案

class AuthGoogle extends AuthGuard('google') {
constructor() {
super({
prompt: 'select_account'
});
} }
}
// using
@UseGuards(AuthGoogle)
private googleAuth() {}

塞巴斯蒂安,你也可以直接从策略类本身执行此操作,而不是专门为调用提示而制作一个警卫。

请在下面查看。

示例代码

只需在策略类中的构造函数调用之后添加它,它就会起作用。您可以直接复制代码。

最新更新