Need assistance with resolving API communication issue on Render.com

I deployed an API web service on Render. The React app is running locally on localhost:3000 as a static site, while the API service runs independently. Everything works locally or even when I send request with Postman. But if i try to send requests to the render web service api I will get a req.user as undefined.

Specifically, when I make requests from our React app to the API endpoints, such as get /user req.user is undefined. On Postman, everything functions as expected, and I can retrieve the necessary data.

I have taken several troubleshooting steps, including verifying the CORS configuration but I think maybe there is a problem with the cookie being sent.

I am using Axios for making HTTP requests from the React app, and I have ensured that withCredentials: true is included in the requests.

const mongoose = require(“mongoose”);
const express = require(“express”);
const cors = require(“cors”);
const passport = require(“passport”);
const passportLocal = require(“passport-local”).Strategy;
const cookieParser = require(“cookie-parser”);
const bcrypt = require(“bcryptjs”);
const session = require(“express-session”);
const bodyParser = require(“body-parser”);
const app = express();
const User = require(“./user”);

//----------------------------------------- END OF IMPORTS---------------------------------------------------
// connect to db
mongoose.connect(
“mongodb+srv://authadmin:{mypassword}@authentication.ouhpl8j.mongodb.net/”,
{
useNewUrlParser: true,
useUnifiedTopology: true,
}
);

// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
cors({
origin: “http://localhost:3000”, // ← location of the react app were connecting to
credentials: true,
})
);
app.use(
session({
secret: “secretcode”,
resave: true,
saveUninitialized: true,
})
);
app.use(cookieParser(“secretcode”));
app.use(passport.session());
app.use(passport.initialize());
require(“./passportConfig”)(passport);

//----------------------------------------- END OF MIDDLEWARE---------------------------------------------------

// routes
app.get(“/”, (req, res) => {
res.send(“Hello World!”);
});
app.post(“/login”, (req, res, next) => {
passport.authenticate(“local”, (err, user, info) => {
if (err) throw err;
if (!user) res.send(“No User Exists”);
else {
req.logIn(user, (err) => {
if (err) throw err;
res.send(“Successfully Authenticated”);
console.log(req.user);
});
}
})(req, res, next);
});

app.post(“/register”, async (req, res) => {
try {
const existingUser = await User.findOne({ username: req.body.username });

if (existingUser) {
  res.send("User Already Exists");
} else {
  const hashedPassword = await bcrypt.hash(req.body.password, 10);

  const newUser = new User({
    username: req.body.username,
    password: hashedPassword,
  });

  const savedUser = await newUser.save();
  console.log(savedUser);
  if (savedUser) {
    res.send("User Created");
  } else {
    throw new Error("Error creating user");
  }
}

} catch (err) {
console.error(err);
res.status(500).send(“Server error”);
}
});

app.get(“/user”, (req, res) => {
console.log(“req.user ->”, req.user);
res.send(req.user); // The req.user stores the entire user that has been authenticated inside of it.;
});

app.listen(4000, () => {
console.log(“Server is running on port 4000”);
});

React App

import React, { useState, useEffect } from “react”;
import “./App.css”;
import Axios from “axios”;

function App() {
const [registerUsername, setRegisterUsername] = useState(“”);
const [registerPassword, setRegisterPassword] = useState(“”);
const [loginUsername, setLoginUsername] = useState(“”);
const [loginPassword, setLoginPassword] = useState(“”);
const [data, setData] = useState(null);
const [userExists, setUserExists] = useState(false);

const register = async () => {
let newUser = await Axios.post(
“renderapiurl”,
{
username: registerUsername,
password: registerPassword,
}
);
console.log(newUser.data);
if (newUser.data === “User Already Exists”) {
setUserExists(true);
}
};

const login = async () => {
let loggedInUser = await Axios.post(
“rendapiurl”,
{
username: loginUsername,
password: loginPassword,
},
{ withCredentials: true }
);
console.log(loggedInUser.data);
};

const getUser = async () => {
try {
const response = await Axios.get(
https://simple-auth-api-vgsn.onrender.com/user”,
{
withCredentials: true,
}
);
setData(response.data);
} catch (error) {
console.error(error);
}
};

useEffect(() => {
setUserExists(false);
}, [registerUsername, registerPassword]);

return (



Register


<input
placeholder=“username”
onChange={(e) => setRegisterUsername(e.target.value)}
/>
<input
placeholder=“password”
onChange={(e) => setRegisterPassword(e.target.value)}
/>
Submit
{userExists ? (
<h3 style={{ color: “red” }}>User already exists
) : null}

  <div>
    <h1>Login</h1>
    <input
      placeholder="username"
      onChange={(e) => setLoginUsername(e.target.value)}
    />
    <input
      placeholder="password"
      onChange={(e) => setLoginPassword(e.target.value)}
    />
    <button onClick={login}>Submit</button>
  </div>

  <div>
    <h1>Get User</h1>
    <button onClick={getUser}>Submit</button>
    {data ? <h1>Welcome Back {data.username}</h1> : null}
  </div>
</div>

);
}

export default App;

Hi Tommy,

I believe because your React app and API are not running on the same origin you need to send withCredentials: true or use axios.defaults.withCredentials = true when making the API request. There is more discussion on this at this Stack Overflow post: https://stackoverflow.com/questions/43002444/make-axios-send-cookies-in-its-requests-automatically.

Regards,

Keith
Render Support, UTC+10 :australia:

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.