使用 passport.js 和 ngrok 时,req.user 由于 cors 而未定义

When using passport.js and ngrok, req.user is undefined because of cors

前端是http localhost,后端是https ngrok。当我在前端使用 OAuth 登录并尝试在后端调用 req.user 时,它显示未定义。

另外,如果后端和前端都使用ngrok,也会出现同样的问题。但是,如果我不在后端使用 ngrok 并使用 http 的本地主机,一切正常。

ngrok 命令:ngrok --host-header http 8000

快递:app.ts

import "~/database";
import "~/libs/passport";

import express from "express";
import session from "express-session";
import cors from "cors";
import passport from "passport";
import { router } from "~/routes";

const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(session({ secret: "asdf", resave: false, saveUninitialized: false }));

app.use(cors({ origin: true, credentials: true }));
app.use(passport.initialize());
app.use(passport.session());

app.use("/", router);
app.listen(8000, () => {
  console.log("Server has been started...");
});

反应:App.tsx

import React, { useCallback, useEffect } from "react";
import logo from "./logo.svg";
import "./App.css";

function App() {
  const handleSignIn = useCallback(() => {
    window.location.assign("http://localhost:8000/api/auth");
  }, []);

  useEffect(() => {
    const process = async () => {
      const result = await fetch("http://localhost:8000/api/profile", {
        credentials: "include",
      });
      console.log(await result.json());
    };

    process();
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <button onClick={handleSignIn}>DASD</button>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

没有错误,但 req.user 未定义。

/api/auth

api.get("/", passport.authenticate("github", { scope: ["repo"] }));

/api/auth/回调

api.get(
  "/",
  passport.authenticate("github", {
    failureRedirect: failureURL,
    successRedirect: frontendOrigin,
  })
);

添加:并在前端调用/api/profile,状态为401。

/api/profile

api.get("/", async (req, res) => {
  if (!req.isAuthenticated()) {
    return res.status(401).json();
  }

  const profile: Profile = {
    username: req.user.username,
    name: req.user.name,
    avatarURL: req.user.avatarURL,
  };
  return res.status(200).json(profile);
});

显然你不能

https://ngrok.com/docs/faq

CORS with HTTP Basic Authentication

ngrok's HTTP tunnels will work with CORS, but you cannot use ngrok's --basic-auth option. ngrok's HTTP tunnels allow you to specify basic authentication credentials to protect your tunnels. However, ngrok enforces this policy on all requests, including the preflight OPTIONS requests that are required by the CORS spec. In this case, your application must implement its own basic authentication.

可能是因为你使用了credentials: true,ngrok已经使用了--basic-auth选项。

你能分享抛出的错误吗?