Google 在 React WebApp 调用的 NestJS 后端中使用 PassportStrategy 登录不工作

Google login with PassportStrategy in NestJS backend not working called by React WebApp

我已经在 NestJS 后端实现了 Google 使用 PassportStrategy 登录(NestJS 后端开发基于此指南:https://medium.com/@nielsmeima/auth-in-nest-js-and-angular-463525b6e071)。

@Get('google')
@UseGuards(AuthGuard('google'))
googleLogin()
{
    // initiates the Google OAuth2 login flow
}

@Get('google/callback')
@UseGuards(AuthGuard('google'))
googleLoginCallback(@Req() req, @Res() res)
{
    // handles the Google OAuth2 callback
    const jwt: string = req.user.jwt;
    if (jwt)
        return res.status(HttpStatus.OK).cookie('jwt', jwt, {
            httpOnly: true
        }).redirect('/');
    else 
        res.redirect('http://localhost:4200/login/failure');
}

使用@UseGuards(AuthGuard('google')) 应该启动 google 登录:

super({
        clientID    : 'XXX',     // <- Replace this with your client id
        clientSecret: 'XXX', // <- Replace this with your client secret
        callbackURL : 'http://myapp.herokuapp.com/auth/google/callback',
        passReqToCallback: true,
        scope: ['profile']
    })

如果我将调用 auth/google 放在浏览器的地址栏中,它就可以工作。

如果我从 React WebApp 调用方法 auth/google 它不起作用,网络请求是屏幕截图中的请求。我没有响应的数据。

App Requests

Google Detail

似乎回调没有启动,但是“passReqToCallback: true”有效。

React 前端请求:

fetch("http://<url>/auth/google", {
  method: "GET",
  mode: 'no-cors',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
})
.then(
  (result) => {
        if (result) {
          history.push({
            pathname: '/home'
          });
        }
  },
  (error) => {
    
  }
);

登录成功时的后端日志:

2021-02-18T10:34:02.724706+00:00 heroku[router]: at=info method=GET path="/auth/google/" host=myapp.herokuapp.com request_id=310ac45a-3657-4c5f-96dc-f0a1350429db fwd="93.146.33.170" dyno=web.1 connect=1ms service=10ms status=302 bytes=371 protocol=http

2021-02-18T10:34:03.321194+00:00 app[web.1]: {

2021-02-18T10:34:03.321209+00:00 app[web.1]: id: 'XXX',

2021-02-18T10:34:03.321210+00:00 app[web.1]: displayName: 'XXX',

登录失败时的后端日志:

2021-02-18T10:36:29.284759+00:00 heroku[router]: at=info method=GET path="/auth/google" host=myapp.herokuapp.com request_id=2f56f65b-9236-4710-b029-dd973ec0c9a3 fwd="54.187.137.25" dyno=web.1 connect=0ms service=3ms status=302 bytes=371 protocol=http

nothing else

有什么想法吗?你能帮帮我吗?

谢谢。

您实现 google 登录的方式对于全栈应用程序很有用。由于您使用的是单独的 React 应用程序(我们称之为 SPA),因此您需要进行一些更改。首先,您的后端不需要 /google 端点。该部分应由 SPA 完成。在用户使用 google 登录后,它应该再次将他重定向到 SPA。此重定向将在查询参数中为您提供用户信息和访问令牌。

然后您才将该信息转发到后端的 /google/callback 路由。您已经使用 google 身份验证保护程序进行了 google 令牌验证,因此唯一剩下的就是使用 google 提供给您的信息来登录用户。我想在你的情况下这意味着生成一个 JWT。不要使用 google 提供的令牌。生成您自己的 JWT。

来自 google documentation:

If you use Google Sign-In with an app or site that communicates with a backend server, you might need to identify the currently signed-in user on the server. To do so securely, after a user successfully signs in, send the user's ID token to your server using HTTPS. Then, on the server, verify the integrity of the ID token and use the user information contained in the token to establish a session or create a new account.