简体   繁体   English

即使在 React/Node/Passport 上为 Google 身份验证添加 CORS 选项后仍面临 CORS 错误

[英]Facing CORS error even after adding CORS options on React/Node/Passport for Google Authentication

I am building a simple app with React as frontend and Node/Express/MongoDB as backend.我正在构建一个简单的应用程序,以 React 作为前端,以 Node/Express/MongoDB 作为后端。 I am authenticating user using Passport.我正在使用 Passport 对用户进行身份验证。 Local authentication is working, as well as Google authentication.本地身份验证和 Google 身份验证都在工作。

I just seem to not able to load the google login page through the app.我似乎无法通过应用程序加载谷歌登录页面。 I am getting CORS error.我收到 CORS 错误。 I have shared the error below.我在下面分享了错误。

On React Login page:在 React 登录页面上:


const onClick = async () => {
    await Axios.get('/auth/google');
  };

Proxy Middleware:代理中间件:

const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
  app.use(createProxyMiddleware('/auth', { target: 'http://localhost:4000' }));
};

Node Server.js: app.use('/auth', require('./routes/auth')); Node Server.js: app.use('/auth', require('./routes/auth'));

routes/auth file:路线/授权文件:

const cors = require('cors');

var corsOptions = {
  origin: 'http://localhost:3000',
  methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
  preflightContinue: false,
  optionsSuccessStatus: 204,
};

router.get(
  '/google',
  cors(corsOptions),
  passport.authenticate('google', {
    scope: ['profile', 'email'],
  }),
);

router.get('/google/redirect',cors(corsOptions), passport.authenticate('google'), (req, res) => {
  res.send(req.user);
});

passportconfig.js:护照配置.js:

passport.use(
    new GoogleStrategy(
      {
        clientID: ClientID,
        clientSecret: ClientSecret,
        callbackURL: '/auth/google/redirect',
        proxy: true,
      },
      (accessToken, refreshToken, profile, done) => {
        // passport callback function
        //check if user already exists in our db with the given profile ID
        User.findOne({ googleId: profile.id }).then((currentUser) => {
          if (currentUser) {
            //if we already have a record with the given profile ID
            done(null, currentUser);
          } else {
            //if not, create a new user
            new User({
              googleId: profile.id,
            })
              .save()
              .then((newUser) => {
                done(null, newUser);
              });
          }
        });
      },
    ),
  );

Error:错误:

Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fgoogle%2Fredirect&scope=profile%20email&client_id=<clientID>.apps.googleusercontent.com' (redirected from 'http://localhost:3000/auth/google') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

If I click on the above XMLHttpRequest link, I am able to authenticate and an account is created on my DB with googleID.如果我点击上面的 XMLHttpRequest 链接,我就可以进行身份验证,并使用 googleID 在我的数据库上创建一个帐户。

I have tried different options suggested throughout inte.net, but none of them is working for me.我尝试了整个 inte.net 中建议的不同选项,但没有一个适合我。 I am not sure what is going wrong here.我不确定这里出了什么问题。

According to the documentation , try removing the corsOptions entirely and just use the cors() function in your express middle-ware before any router is declared.根据文档,尝试完全删除corsOptions并在声明任何路由器之前在您的快速中间件中使用cors() function。 Like so:像这样:

app.use(cors());

Let me know if this works.让我知道这个是否奏效。

// step 1:
// onClick handler function of the button should use window.open instead 
// of axios or fetch
const loginHandler = () => window.open("http://[server:port]/auth/google", "_self")

//step 2: 
// on the server's redirect route add this successRedirect object with correct url. 
// Remember! it's your clients root url!!! 
router.get(
    '/google/redirect', 
    passport.authenticate('google',{
        successRedirect: "[your CLIENT root url/ example: http://localhost:3000]"
    })
)

// step 3:
// create a new server route that will send back the user info when called after the authentication 
// is completed. you can use a custom authenticate middleware to make sure that user has indeed 
// been authenticated
router.get('/getUser',authenticated, (req, res)=> res.send(req.user))

// here is an example of a custom authenticate express middleware 
const authenticated = (req,res,next)=>{
    const customError = new Error('you are not logged in');
    customError.statusCode = 401;
    (!req.user) ? next(customError) : next()
}
// step 4: 
// on your client's app.js component make the axios or fetch call to get the user from the 
// route that you have just created. This bit could be done many different ways... your call.
const [user, setUser] = useState()
useEffect(() => {
    axios.get('http://[server:port]/getUser',{withCredentials : true})
    .then(response => response.data && setUser(response.data) )
},[])

Explanation....解释....
step 1 will load your servers auth url on your browser and make the auth request.第 1 步将在您的浏览器上加载您的服务器身份验证 url 并发出身份验证请求。
step 2 then reload the client url on the browser when the authentication is complete.步骤2然后在身份验证完成后在浏览器上重新加载客户端url。
step 3 makes an api endpoint available to collect user info to update the react state第 3 步使 api 端点可用于收集用户信息以更新反应 state
step 4 makes a call to the endpoint, fetches data and updates the users state.第 4 步调用端点,获取数据并更新用户 state。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM