node.js - COR 错误 : Google Oauth from React to Express (PassportJs validation)

标签 node.js reactjs express oauth-2.0 passport.js

我正在尝试使用 Google OAuth 身份验证设置 React/Redux - NodeJs Express 堆栈。我的问题是控制台中出现的 COR 错误。我发现了一些我认为正是我的问题的 Stack Overflow 问题,但这些解决方案没有产生任何结果。特别是这两个:CORS with google oauthCORS/CORB issue with React/Node/Express and google OAuth .

所以我尝试了各种修复方法,但似乎都让我回到了同样的错误。这是其中最直接的:

const corsOptions = {
    origin: 'http://localhost:3000',
    optionsSuccessStatus: 200,
    credentials: true
}
app.use(cors(corsOptions));

这是在我的 API.js 文件的根目录中。我收到的控制台错误状态:

Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fapi%2Foauth%2Fgoogle%2Freturn&scope=profile&client_id=PRIVATE_CLIENT_ID.apps.googleusercontent.com' (redirected from 'http://localhost:5000/api/oauth/google') from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

因此,如果我在开发工具中查看我的网络日志,我会查看我对 API 路径的请求并查看我期望看到的内容:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: http://localhost:3000

所以在我看来,我的问题不在于我的前后沟通。这让我相信这可能是 Passport token 验证的问题。这是我的简化路线:

router.post('/oauth/google', passport.authenticate('googleVerification', {
    scope: ['profile']
}), (req, res) => {
    console.log('Passport has verified the oauth token...');
    res.status(200)
});

以及回调路由:

router.get('/oauth/google/return', (req, res) => {
    console.log('google oauth return has been reached...')
    res.status(200)
});

最后,简化的策略:

passport.use('googleVerification', new GoogleStrategy({
    clientID: process.env.OAUTH_CLIENT_ID,
    clientSecret: process.env.OAUTH_SECRET,
    callbackURL: 'http://localhost:5000/api/oauth/google/return'
}, (accessToken, refreshToken, profile, cb) => {
    console.log('Passport OAuth Strategy reached');
    cb(null, profile)
}));

我知道所有这些都不会导致任何功能,但我只是尽可能多地扯掉了绒毛,试图弄清楚我的身份验证流程中的 block 在哪里。以防万一它可能有助于缩小范围,这里是 Redux 中的操作创建者,它在错误开始之前记录流程中的最后一步('redux 接受 token 并传递给 API:', token ):

export const signIn = (token) => {
    console.log('redux accepting token and passing to API:', token)
    return async dispatch => {
        const res = await Axios({
            method: 'post',
            url: `${API_ROOT}/api/oauth/google`,
            withCredentials: true,
            data: {
                access_token: token
            }
        })

        console.log('API has returned a response to redux:', res)

        dispatch({
            type: SIGN_IN,
            payload: res
        })
    }
};

这实际上永远不会到达返回,并且不会记录第二个 console.log 以供记录。

最佳答案

CORS 与向 google 提出请求无关,因为当您在 console.developers.google.com 中注册您的应用时,它已由 google 处理。 p>

CRA 开发者服务器express api 服务器 之间存在问题。您正在从 localhost:3000localhost:5000 发出请求。要解决此问题,请使用代理。

在客户端目录中:

npm i http-proxy-middleware --save

client/src 中创建 setupProxy.js 文件。无需在任何地方导入。 create-react-app 会寻找这个目录

将您的代理添加到此文件:

module.exports = function(app) {
    app.use(proxy("/auth/google", { target: "http://localhost:5000" }));
    app.use(proxy("/api/**", { target: "http://localhost:5000" }));
};

我们说的是做一个代理,如果有人试图访问我们的 react 服务器上的路由/api 或/auth/google,自动将请求转发到 localhost:5000

这里是更多详细信息的链接:

https://create-react-app.dev/docs/proxying-api-requests-in-development/

默认情况下,password.js 不允许代理请求。

passport.use('googleVerification', new GoogleStrategy({
    clientID: process.env.OAUTH_CLIENT_ID,
    clientSecret: process.env.OAUTH_SECRET,
    callbackURL: 'http://localhost:5000/api/oauth/google/return',
    proxy:true
}

这里很重要的一点是,您应该了解为什么要使用代理。据我从您的代码中了解,从浏览器中,您提出了 express 请求,express 将使用 password.js 处理身份验证。在password.js运行完所有的认证步骤后,它会创建一个cookie,把id塞进去,交给express,express会发送到浏览器。这是您的应用结构:

 BROWSER ==> EXPRESS ==> GOOGLE-SERVER

浏览器会自动将 cookie 附加到发出 cookie 的服务器的每个请求中。所以浏览器知道哪个cookie属于哪个服务器,所以当他们向那个服务器发出新请求时,它们会附加它。但是在您的应用程序结构中,浏览器不与 GOOGLE-SERVER 对话。如果你没有使用代理,你会通过 express 从 GOOGLE-SERVER 获取 cookie,但由于你没有向 GOOGLE-SERVER 发出请求,cookie 不会被使用,它不会被自动附加。这就是使用 cookie 的重点,浏览器会自动附加 cookie。通过设置代理,现在浏览器不知道 GOOGLE-SERVER。据它所知,它正在向 express 服务器发出请求。所以每次浏览器请求使用相同的端口表达时,它都会附加cookie。我希望这部分很清楚。

现在 react 只与 express-server 通信。

  BROWSER ==> EXPRESS

由于 react 和 exress 不在同一个端口上,你会得到 cors 错误。

有两种解决方案。 1 正在使用 cors包。

它的设置非常简单

var express = require('express')
var cors = require('cors')
var app = express()
 
app.use(cors()) // use this before route handlers

第二种解决方案是在路由处理程序之前手动设置中间件

app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Methods",
    "OPTIONS, GET, POST, PUT, PATCH, DELETE"
  );
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
  next(); // dont forget this
});

关于node.js - COR 错误 : Google Oauth from React to Express (PassportJs validation),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59036377/

相关文章:

javascript - React Issue - 子状态更改父状态

javascript - React Navigation : Navigate Back To Root using NavigationActions. 重置、goBack 和 getStateForAction

ruby-on-rails-3 - 直接从 Rails 应用程序向 Node.js 和 Socket.io 推送服务器发送消息

angularjs - AWS文件上传超过5mb-nodejs

node.js - nodejs - IF 和 ELSE 都执行

node.js - 如何让 express-basic-auth 提示弹出用户和密码?

node.js - 在 forEach 循环中运行 sequelize 查询。无法处理结果

javascript - NodeJS - 从 Google Drive 下载

javascript - 具有间隔更新的 React 时钟组件非常慢

node.js - 为什么会发生这个错误? Node 错误 : write EIO