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;