Home > Software engineering >  When using passport.js and ngrok, req.user is undefined because of cors
When using passport.js and ngrok, req.user is undefined because of cors

Time:05-24

The frontend is http localhost and the backend is https ngrok. When I log in with OAuth in the frontend and try to call req.user in the backend, it says undefined.

Also, if both the backend and the frontend use ngrok, the same problem occurs. However, if I do not use ngrok in the backend and use the localhost which is http, everything works fine.

ngrok command: ngrok --host-header http 8000

Express: 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...");
});

React: 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;

There's no error, but req.user is undefined.

/api/auth

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

/api/auth/callback

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

Add: and call /api/profile in frontend, status is 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);
});

CodePudding user response:

Apparently you can't

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.

It might be because you yuse credentials: true, ngrok already uses --basic-auth option.

Can you share the error thrown ?

  • Related