After login post, you server redirects to the root, which returns the app listening html, but html requests don’t support CORS. Also your react fetch is expecting a data response, not an html page.
blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
i have a react app with a app folder for the frontend and e api folder for the backend. The api folder has a index.js from where i start my server.
In the app folder and more likely my frontend folder i have a hook wich calls UseMutation.js. I use that in my login.js in my forntend folder to login the user.
I have one problem and its the cors, i won't work and i've tried everything. Can someone help my pls?
this is my index.js of my backend
import "dotenv/config";
import express from "express";
import { ObjectId } from "mongodb";
import { initClient } from "./db/mongo.js";
import { registerMiddleware } from "./middleware/index.js";
import bcrypt from "bcrypt";
import session from "express-session";
import passport from "passport";
import { Strategy as LocalStrategy } from "passport-local";
import cors from "cors";
// create an Express app
const app = express();
// set the port for the server to listen on
const port = 3002;
// register middleware
// initialize MongoDB client and database
const client = await initClient();
const db = client.db();
app.use(
session({
secret: "your-secret-key",
resave: false,
saveUninitialized: false,
})
);
app.use(passport.initialize());
app.use(passport.session());
passport.use(
new LocalStrategy(async (username, password, done) => {
try {
// check if user exists in the database
const user = await db.collection("users").findOne({ username });
if (!user) {
// User not found
return done(null, false);
}
// compare the provided password with the stored hashed password
const isPasswordValid = await bcrypt.compare(password, user.hashedPassword);
if (!isPasswordValid) {
// Incorrect password
return done(null, false);
}
// Authentication successful
return done(null, user);
} catch (error) {
return done(error);
}
})
);
passport.serializeUser((user, done) => {
done(null, user._id);
});
// Deserialize user object from the session
passport.deserializeUser(async (id, done) => {
try {
const user = await db.collection("users").findOne({ _id: ObjectId(id) });
done(null, user);
} catch (error) {
done(error);
}
});
app.use(cors({
origin: "http://localhost:3000", // Vervang door de juiste oorsprong
methods: "GET, POST, PUT, DELETE", // Vervang door de toegestane methoden
allowedHeaders: "Content-Type", // Vervang door de toegestane headers
credentials: true, // Schakel cookies en verificatie in indien nodig
optionsSuccessStatus: 200
}));
app.post(
"/login",
passport.authenticate("local", {
successRedirect: "http://localhost:3000",
failureRedirect: "http://localhost:3000",
})
);
// define a route to handle user login
app.post("/register", async (req, res) => {
const { username, password } = req.body;
// check if user exists in the database
let user = await db.collection("users").findOne({ username });
// if not, add user to the database
if (!user) {
const hashedPassword = await bcrypt.hash(password, 10);
await db.collection("users").insertOne({ username , hashedPassword });
user = await db.collection("users").findOne({ username, hashedPassword });
}
// send back the user object
res.json(user);
console.log(user);
});
// define a router for authenticated routes
const authRouter = express.Router();
// middleware for authentication
authRouter.use(async (req, res, next) => {
// check if authorization header exists
if (req.headers.authorization) {
// check if user with id exists
const user = await db
.collection("users")
.findOne({ _id: ObjectId(req.headers.authorization) });
// if user exists, pass user object to the request object
if (user) {
req.user = user;
return next();
}
}
// if user not authenticated, send back 401 error
res.status(401).json({
error: "Unauthorized",
});
});
// define a route to get all students
authRouter.get("/rent", async (req, res) => {
console.log(req.user);
const users = await db.collection("users").find().toArray();
res.json(users);
});
// define a route to add a new student
authRouter.post("/students", async (req, res) => {
const student = {
image:
"https://picsum.photos/200/300",
...req.body,
};
await db.collection("students").insertOne(student);
// return added student
res.json(student);
});
// define a route to get a student by id
authRouter.get("/students/:id", async (req, res) => {
const id = req.params.id;
const student = await db.collection("students").findOne({
_id: ObjectId(id),
});
// if student exists, send back student object
if (student) {
res.json(student);
} else {
// if student not found, send back 404 error
res.status(404).json({ error: "Not found" });
}
});
// define a route to update a student by id
authRouter.patch("/students/:id", async (req, res) => {
const id = req.params.id;
// check if student exists
const student = await db
.collection("students")
.findOne({ _id: ObjectId(id) });
// if student exists, update student data
if (student) {
const { _id, ...data } = req.body;
const newData = { ...student, ...data };
await db.collection("students").replaceOne({ _id: ObjectId(id) }, newData);
res.json(newData);
} else {
res.status(404).json({ error: "Not found" });
}
});
// DELETE
authRouter.delete("/students/:id", async (req, res) => {
const id = req.params.id;
await db.collection("students").deleteOne({
_id: ObjectId(id),
});
res.json({});
});
app.listen(port, () => {
console.log(`App listening http://localhost:${port}`);
});
// make sure database is closed when server crashes
const closeServer = () => {
// default
process.exit();
};
process.on("SIGINT", () => closeServer());
process.on("SIGTERM", () => closeServer());
//https://www.geeksforgeeks.org/node-js-process-signal-events/
this is the Mutation.js
// Importing useState and the custom hooks for authentication and handling API errors
import { useState } from "react";
import { useAuthContext } from "../contexts/AuthContainer";
import { handleErrors } from "../helpers/api";
const useMutation = () => {
// Getting the user authentication data from the context API
const auth = useAuthContext();
// Initializing the state variables for loading and errors
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState();
// This function is responsible for making an API call with the given url and options
const mutate = async (url, options = {}) => {
// Set the loading state to true
setIsLoading(true);
// Setting the headers for the request
const headers = {
accept: "application/json",
"content-type": "application/json",
};
// Only add the user authentication data to headers if it exists
if (auth && auth.user) {
headers.Authorization = auth.user._id;
}
try {
// Making a fetch call with the given url and options, including the headers
const result = await fetch(url, {
method: options.method ?? "POST",
headers: headers,
body: JSON.stringify(options.data ?? {}),
});
// Handling errors in the response using the handleErrors function
const data = await handleErrors(result);
// If there's a success callback, call it with the response data, otherwise set loading state to false
if (options.onSuccess) {
options.onSuccess(data);
} else {
setIsLoading(false);
}
} catch (error) {
// If there's an error callback, call it with the error, otherwise set the error state and loading state to false
if (options.onError) {
options.onError(error);
} else {
setIsLoading(false);
setError(String(error));
}
}
};
// Returning the loading state, error state, and the mutate function to make API calls
return {
isLoading,
error,
mutate,
};
};
// Exporting the useMutation hook
export default useMutation;
and this is my login.js
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import Button from "../../components/Global/Button/Button";
import Input from "../../components/Global/Input/Input";
import Title from "../../components/Global/Title/Title";
import useMutation from "../../hooks/useMutation";
const Login = ({ onLogin }) => {
const [data, setData] = useState({
username: "",
password: "",
});
const { isLoading, error, mutate } = useMutation();
const navigate = useNavigate();
const handleChange = (e) => {
setData({
...data,
[e.target.name]: e.target.value,
});
};
const handleSubmit = (e) => {
e.preventDefault();
mutate(`${process.env.REACT_APP_API_URL}/login`, {
method: "POST",
data,
onSuccess: (data) => {
onLogin(data);
},
credentials: "include",
});
};
return (
<>
<form>
{error && <p>{error}</p>}
<label>Username</label>
<input type="text" name="username" value="{data.username}">
<label>Password</label>
<input type="password" name="password" value="{data.password}">
<button type="submit" disabled="{isLoading}">
Login
</button>
</form>
);
};
export default Login;
i get this error
Access to fetch at 'http://localhost:3000/' (redirected from 'http://localhost:3002/login') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
thnx in advance!