简体   繁体   English

在 React/Express 中使用 PassportJS for Google OAuth 时出现 CORS 错误

[英]Getting CORS error when using PassportJS for Google OAuth in React/Express

Despite looking for hours I cannot find a solution to my simple cors error.尽管找了几个小时,我还是找不到简单的 cors 错误的解决方案。 I am getting the following the in the browser:我在浏览器中得到以下内容:

Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fapi%2Fauth%2Fauth%2Fgoogle%2Fcallback&scope=profile%20email&client_id=******.apps.googleusercontent.com' (redirected from 'http://localhost:3000/api/auth/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.在 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fapi%2Fauth%2Fauth%2Fgoogle%2Fcallback&scope=profile%20email&client_id 访问 XMLHttpRequest =******.apps.googleusercontent.com'(从 'http://localhost:3000/api/auth/auth/google' 重定向)来自 'http://localhost:3000' 已被阻止CORS 策略:请求的资源上不存在“Access-Control-Allow-Origin”header。

I just replaced the client ID for security reasons for this post.为了这篇文章的安全原因,我刚刚替换了客户端 ID。 When I make this call in Postman/Thunder Client it gives back a 200 response and seems to work fine当我在 Postman/Thunder Client 中进行此调用时,它会返回 200 响应并且似乎工作正常

So I have tried using cors NPM package in express app.use(cors());所以我尝试在快递app.use(cors()); also tried using this function in server.js app.all("/*", function (req, res, next) { res.header("Access-Control-Allow-Origin", "*"); next(); });还尝试在 server.js app.all("/*", function (req, res, next) { res.header("Access-Control-Allow-Origin", "*"); next(); }); I've also tried using `我也尝试过使用`

const proxy = require('http-proxy-middleware');

module.exports = function(app) {
    app.use(proxy("/api/auth/auth/google", {
          target: "https://localhost:3000/",
          changeOrigin: true
    }));
}

I've just about done every solution in the book I found on SO, and none have seemed to work thus far.我刚刚完成了我在 SO 上找到的书中的所有解决方案,但到目前为止似乎没有一个有效。 Any help would be so appreciated Here is my code:任何帮助将不胜感激这是我的代码:

Package.json in client Package.json在客户端

{
  "name": "tasktracker",
  "proxy": "http://localhost:3001/",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.13.0",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "axios": "^0.21.1",
    "http-proxy-middleware": "^2.0.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-router-dom": "^5.2.0",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.1.2"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Homepage.js主页.js

import React from "react";
import API from "../components/utils/API";

export default function HomePage() {
  const handleLogin = () => {
    API.login();
  };
  const testing = () => {
    console.log("Hello world!");
    API.testing();
  };

  return (
    <div>
      <h1>Let's login with Google</h1>
      <button onClick={handleLogin}>Login</button>
      <button onClick={testing}>Testing</button>
    </div>
  );
}

API.js API.js

import axios from "axios";
export default {
  login: function () {
    return axios.get("/api/auth/auth/google");
  },
  testing: function () {
    return axios.get("/api/auth/test");
  },
};

Server.js服务器.js

const express = require("express");
const passport = require("passport");
const routes = require("./routes");
const app = express();
const PORT = process.env.PORT || 3001;
const cors = require("cors");

app.use(cors());

// Define middleware here
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
require("./config/passport");
app.use(passport.initialize());

// Add routes, both API and view
app.use(routes);


// Start the API server
app.listen(PORT, function () {
  console.log(`🌎  ==> API Server now listening on PORT ${PORT}!`);
});

auth.js (auth routes) auth.js (认证路由)

const router = require("express").Router();
const passport = require("passport");
const cors = require("cors");
const CLIENT_HOME_PAGE_URL = "http://localhost:3000";

/Route is api/auth/test
router.get("/test", function (req, res) {
  res.send(console.log("Test to backend"));
});


//Route is api/auth/auth/google/callback
router.get(
  "/auth/google/callback",
  passport.authenticate("google", {
    successRedirect: CLIENT_HOME_PAGE_URL,
    failureRedirect: "/",
    session: false,
  }),
  function (req, res) {
    var token = req.user.token;
    res.redirect("http://localhost:3000?token=" + token);
  }
);


  //Route is api/auth/auth/google/
router.get(
  "/auth/google",

  passport.authenticate("google", { scope: ["profile", "email"] })
);

module.exports = router;

Passport.js Passport.js

var passport = require("passport");
var GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;

passport.serializeUser(function (user, done) {
  done(null, user);
});

passport.deserializeUser(function (user, done) {
  done(null, user);
});

passport.use(
  new GoogleStrategy(
    {
      clientID:
        "*****",
      clientSecret: "*****",
      callbackURL: "http://localhost:3001/api/auth/auth/google/callback",
    },
    function (accessToken, refreshToken, profile, done) {
      var userData = {
        email: profile.emails[0].value,
        name: profile.displayName,
        token: accessToken,
      };
      done(null, userData);
    }
  )
);

I know it's a bit of a long post, if anyone has any ideas or solutions would greatly help me a lot.我知道这篇文章有点长,如果有人有任何想法或解决方案会对我有很大帮助。

I was facing the same problem recently.我最近面临同样的问题。 Using使用

window.location.href = "http://localhost:5000/api/auth/google" 

instead of代替

axios.get("/api/auth/auth/google") 

solved the problem.解决了这个问题。

On successful authentication, if you want to redirect the user to the original url on which the user made the login request, you can do this...成功认证后,如果要将用户重定向到用户发出登录请求的原始 url,您可以这样做...

const currentUrl = window.location.href
const encodedParam = encodeURI(`?redirectUrl=${currentUrl}`)
window.location.href = `http://localhost:5000/api/auth/google${encodedParam}`

Store the redirect value in a session将重定向值存储在 session

req.session.redirectPath = req.query.redirectUrl

and after authentication, use this in your callback route并在身份验证后,在您的回调路由中使用它

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

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