React+Expressjs Deployment - reactjs

I am trying to Test if my build file is ok, Therefore what I did was to build client and move build directory to server.
and in the index.js of backend => to open HTML of Build folder.(I do not know if this is right thing to do)
app.get("/", function (req, res) {
res.sendFile(__dirname + "/build/index.html");
});
Following folderStructure
-client
=>src(react Code)
-server
=>Build(which is from react 'npm run build')
=>BackendCode
I have implemented Login Routes one for Post login, and one for get login which is
GET:
router.get("/login", async (req, res) => {
console.log("getLogin ses.user: ", req.session.user);
console.log("getLogin ses.isLogIn?: ", req.session.isLoggedIn);
if (req.session.user) {
return res.send({
isLoggedIn: true,
user: req.session.user,
isAdmin: req.session.isAdmin,
isVerified: req.session.isVerified,
pwFlag: req.session.pwFlag,
});
} else {
return res.send({ isLoggedIn: false });
}
});
POST:
router.post("/login", isNotLoggedIn, async (req, res) => {
-- user find in DB and compare Password in db Logic...--
if(user){
req.session.save((err) => {
if (err) console.log(err);
console.log("Session Saved!!!!: ", req.session);
logger.info(`LOGIN POST/ ${req.session.user.email}`);
return res.status(200).send({
user: sessionUser,
isAdmin: req.session.isAdmin,
pwFlag: req.session.pwFlag,
});
})
})
with this two route, when i do router.post for login it works.
REACT CODE=>
Login Submit form
const onLoginSubmit = async (e) => {
e.preventDefault();
setLoading(true);
const req = { email, password };
const res = await fetch(`${serverUrl}/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "include", //to let cookie to go to server
body: JSON.stringify(req),
});
const data = await res.json();
if (res.ok) {
console.log("login success");
setLoginStat(true);
setIsAdmin(data.isAdmin);
setUser(data.user);
setPwFlag(data.pwFlag);
if (data.user) {
setLoading(false);
navigate("/");
}
} else {
alert(data.message);
setLoading(false);
}
};
and in the App.js of React,
useEffect(() => {
checkLogin();
}, []);
async function checkLogin() {
const res = await fetch(`${serverUrl}/login`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
credentials: "include",
});
try {
const data = await res.json();
console.log("App useEffect: ", data);
if (res.ok) {
console.log(data);
setLoginStat(data.isLoggedIn);
setUser(data.user);
setIsAdmin(data.isAdmin);
setIsVerif(data.isVerified);
setPwFlag(data.pwFlag);
}
} catch (err) {
setLoginStat(false);
}
}
so the Login Post works well it make me to go to main page. but when I go to different Page that has useEffect to fetch Data, and backend with middle where "isLoggedIn" :
ex)router.get("/something", isLoggedIn, async(req,res)=>{...})
async function isLoggedIn(req, res, next) {
console.log("MW => isLoggedIn:", req.session.user);
console.log("MW => session:", req.session);
if (req.session.isLoggedIn && req.session.user) {
next();
} else {
return res.status(401).send({ message: "Did not login 🚫" });
}
}
it say that MW => isLoggedIn: undefined session being gone. I really dont know why this is happening
To give Detail here is my index.js of server Setting:
const cors = require("cors");
const express = require("express");
const session = require("express-session");
...
app.use(
session({
store: MongoStore.create({
mongoUrl: process.env.MONGO_URL,
collection: "sessions",
ttl: 1 * 24 * 60 * 60, //this is One day
}),
secret: process.env.MONGO_SESSION_SECRET,
resave: false,
saveUninitialized: true,
cookie: {
expires: 60 * 60 * 1000, //one hour
secure: false,
httpOnly: false,
// maxAge: 3600000, //one hour
sameSite: "none",
},
name: "scm",
//5000 === 5sec
})
);
app.set("trust proxy", 1);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, authorization, Set-Cookie"
);
res.header("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
next();
});
...
app.use(
cors({
origin: true,
// [
// "http://localhost:5000",
// "http://192.168.80.64:3000",
// "http://localhost:3000",
// ],
proxy: true,
credentials: true,
methods: ["HEAD", "POST", "PUT", "GET", "PATCH", "DELETE"],
})
);
...
app.get("/", function (req, res) {
res.sendFile(__dirname + "/build/index.html");
});
it works fine with npm run start on reactjs. it just does not work with build files. Thank you in advance

React application will serve through the entry build/index.html. This file has to be picked up by the back end server to serve the front end application: import the path module and add
app.use(express.static(path.resolve(__dirname, "./build")));
app.get("/", (req, res) => {
res.sendFile(path.resolve(__dirname, "./build", "index.html"));
});
See Refrece.

Related

Using axios / fetch to fetch data from node toreact

Please I need a help on how to fetch a data from node to react, I have been stuck here for 2 weeks now.
Here are my backend code:
server.js:
require("dotenv").config();
const app = require("./src/app");
const port = process.env.PORT || 4000;
app.get("/", (req, res) => {
res.send("Hello World!");
});
app.listen(port, () => {
console.log(`Server is running on port http://localhost:${port}`);
});
app.js:
const express = require("express");
const cors = require("cors");
const cookieSession = require("cookie-session");
const app = express();
app.use(
cors({
origin: ["http://localhost:4000/api", "http://localhost:3000"],
})
);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.use(express.json());
app.use(express({ type: "application/vnd.api+json" }));
app.use(express.urlencoded({ extended: true }));
app.use(
cookieSession({
name: process.env.COOKIE_NAME, //ookie name in .env
secret: process.env.COOKIE_SECRET, //secret name in .env
httpOnly: true,
sameSite: "strict",
maxAge: 24 * 60 * 60 * 1000, // 24 hours duration before expire
})
);
app.use("/uploads", express.static("uploads"));
const jobRoute = require("./routes/job.routes");
app.use("/api/", jobRoute);
module.exports = app;
service.js:
const db = require("../config/database");
const notificationServices = require("./notification.services");
const { jobReuseQuery } = require("../job reuseable query/job.queries");
const createJob = async (body) => {
const {
title,
salary_type,
salary,
job_types,
description,
company_id,
sector_id,
category_id,
} = body;
const { rows } = await db.query(
`INSERT INTO jobs (title, salary_type, salary, job_types, description, company_id, sector_id, category_id)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *`,
[
title,
salary_type,
salary,
job_types,
description,
company_id,
sector_id,
category_id,
]
);
notificationServices.sendMatchJobsToUserProfiles(rows[0]);
return rows[0];
};
const getAllJobs = async () => {
const { rows } = await db.query("SELECT * FROM jobs");
return rows;
};
controller.js:
const jobService = require("../services/job.services");
const createJob = async (req, res) => {
try {
const job = await jobService.createJob(req.body);
res.status(201).send({
message: "Job created successfully",
data: job,
});
} catch (err) {
res.status(400).send(err.message);
}
};
const getAllJobs = async (req, res) => {
try {
const jobs = await jobService.getAllJobs();
res.status(200).send({ data: jobs });
} catch (err) {
res.status(400).send({ message: err.message });
}
};
routes.js:
const router = require("express-promise-router")();
const jobController = require("../controllers/job.controller");
const auth = require("../middleware/auth.middleware");
router.post("/jobs", auth, jobController.createJob);
auth.js:
const db = require("../config/database");
const jwt = require("jsonwebtoken");
const dotenv = require("dotenv");
dotenv.config();
const auth = async (req, res, next) => {
const token = req.session.token;
if (!token) {
return res.status(401).send({ error: "Please Authenticate" });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const { rows } = await db.query("SELECT * FROM users WHERE id = $1", [
decoded.id,
]);
if (!rows[0]) {
throw new Error("User not found");
}
req.user = rows[0];
next();
} catch (error) {
return res.status(401).send({ error: error.message });
}
};
module.exports = auth;
React frontend code:
import React, { useEffect } from "react";
import tech from "../../image/tech-big.svg";
import health from "../../image/health-big.svg";
import eng from "../../image/eng-big.svg";
import axios from "axios";
import { useState } from "react";
const Joblist = () => {
const [name, setName] = useState([]);
//first method
const response = axios
.get("http://localhost:4000/api/jobs/")
.then((res) => res.json());
console.log(response);
//second method
const fetchData = async () => {
const newData = await fetch("http:localhost:4000/api/jobs", {
method: "GET",
headers: {
"Content-Type": "application/json",
ACCEPT: "application/json",
"Access-Control-Allow-Credentials": true,
"Access-Control-Allow-Origin": true,
credentials: "same-origin",
Authorization: `Bearer ${token}`,
},
}).then((res) => res.json());
console.log(newData);
setName(newData.jobs.name);
fetchData();
};
you can see in my react, I have 2 method i used trying to fetch the data fron node to the react
first method return error in my browser console :
Promise {<pending>}
GET http://localhost:4000/api/jobs/ 401 (Unauthorized)
Uncaught (in promise) AxiosError {message: 'Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}
while the second method return nothing in my browser console
I am trying to fetch a data from my node backend into frontend react but my first method log error while the second method log nothing
I think you need to clean up a bit your setting, since you're using CORS than you can first make some changes :
// .....
const app = express();
// with CORS you can do all your setting at the same place, so you don't need to set the header
const corsOptions = {
origin: ["http://localhost:4000/api", "http://localhost:3000"],
methods: "GET, POST, PUT, DELETE, OPTIONS, HEAD",
credentials: true, // for jwt/cookie !
};
app.use(cors(corsOptions));
app.use(express.json());
app.use(express({ type: "application/vnd.api+json" }));
app.use(express.urlencoded({ extended: true }));
app.use(
cookieSession({
name: process.env.COOKIE_NAME,
secret: process.env.COOKIE_SECRET,
maxAge: 24 * 60 * 60 * 1000,
httpOnly: true,
sameSite: false, //set this to "None" if you deploy to production on cross domaine.
secure: false, //set to true is required on production with https
});
app.use("/uploads", express.static("uploads"));
const jobRoute = require("./routes/job.routes");
app.use("/api/", jobRoute);
module.exports = app;
Update the fetch part I clean up (I remove the header) and i just notice on your job.controller.js you put data property on your response json.. so you need to check again your database structure if it's still not working.
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("http:localhost:4000/api/jobs", {
credentials: "include", //to be able to send with cookies...
});
if(response.ok) {
const newData = await response.json();
console.log(newData);
setName(newData.data.jobs.name); // this part you need to check your data structure again...
}
} catch (error) {
console.log(error)
}
}
fetchData();
}, []);
Optional note: this part is not part of your question, just in case if there is still issue with the cookie-session and jwtoken, you can change how the JWT is stored in the cookie: cookie-session purpose is to create a "session id" to authenticate the user by storing it at the client side (on the browser, with the cookie), i don't really see the point to use this if you're gonna use jwt token to authenticate anyway ? I let you see the step below if you re still stuck at this part:
First, you may need to install cookie-parser middleware, because if this method work for you, you will be able to uninstall cookie-session.
const cookieParser = require('cookie-parser')
/...
app.use(cookieParser());
on the auth.controllers.js
const loginAuth = async (req, res) => {
try {
const token = await authServices.login(req.body);
// set the jwt token on the cookie
res.cookie("jwt", token, {
maxAge: 24 * 60 * 60 * 1000,
httpOnly: true,
sameSite: false, //set this to "None" if you deploy to production on cross domaine.
secure: false, //set to true is required on production with https
})
return res.status(200).json({
//controller will return this message if the body sent was match
message: "User logged in successfully!",
});
} catch (error) {
//ratther it will return this erroe message
return res.status(500).json({ message: error.message });
}
};
//create a logout session for the user to logout by signing session to null
const logoutAuth = async (req, res) => {
res.clearCookie("jwt")
return res.status(200).send({ message: "User logged out successfully!" });
};
You also need to replace const token = req.session.token; in your activeAuth function, and in your auth.middleware.js at the auth middleware function by this:
const token = req.cookies["jwt"] //or
const token = req.cookies.jwt
Finally if it work you can uninstall cookie-session.

Passport.js authentication in ExpressJS not returning res.user in React

I've followed a guide on Medium on the implementation of Passport js with a MERN stack and whilst I got authentication to work, I'm struggling to persist users between routes. Below are snippets of my code:
Backend
Server.js setup (part of it):
const mongoose = require('mongoose')
const MongoStore = require('connect-mongo')
const passport = require('./passport/setup')
const MONGO_URI = 'db'
const app = express();
mongoose
.connect(MONGO_URI, { useNewUrlParser: true })
.then(console.log(`MongoDB connected ${MONGO_URI}`))
.catch(err => console.log(err))
app.set("")
const PORT = process.env.PORT || 5000;
if (PORT !== 5000) {
app.use(enforce.HTTPS({ trustProtoHeader: true }));
}
app.use(cors({
origin: true,
credentials: true,
}))
app.options('*', cors())
app.use(
session({
secret: "secret",
resave: false,
saveUninitialized: true,
store: MongoStore.create({ mongoUrl: MONGO_URI })
})
);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(passport.initialize());
app.use(passport.session());
Passport.js Local Strategy setup:
const bcrypt = require('bcryptjs');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/User')
passport.serializeUser((user, done) => {
done(null, user.id);
})
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
passport.use(new LocalStrategy({ usernameField: "email" }, (email, password, done) => {
User.findOne({ email: email })
.then(user => {
if (!user) {
return done(null, false, { message: 'No User Found' })
} else {
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: "Wrong Password" });
}
});
}
})
.catch(err => {
return done(null, false, { message: err });
});
})
);
module.exports = passport;
Login route:
router.post("/new-login", async (req, res, next) => {
passport.authenticate("local", function (err, user, info) {
if (err) {
return res.status(400).json({ errors: err });
}
if (!user) {
return res.status(400).json({ errors: "No user found" });
}
req.logIn(user, function (err) {
if (err) {
return res.status(400).json({ errors: err });
}
return res.status(200).json({ success: `logged in ${user.id}` });
});
})(req, res, next);
})
Frontend React:
Posting Login Data:
export const postData = async (url, data) => {
try {
console.log('posting this ', data)
const config = {
withCredentials: true,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'backend',
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE'
}
}
const response = await axios.post(url, data, config);
console.log('getting this', response)
return {
data: response.data,
error: "",
success: true,
};
} catch (exp) {
console.log('Error', exp)
return {
success: false,
error: exp.response.data,
};
}
};
Axios call:
let response = await postData('/login/new-login', { email, password })
When trying to login all of this works and returns the login success message with user.id from the login route, but when I look at the Axios response there's no reference to any user or session as shown below:
I'm probably not understanding how users are passed to React from the backend but shouldn't res.user exist here following req.LogIn in Passport? Or should I take the user.id and save it in a global React state and attach it every time I do a request to a protected route? Right now if I do a GET request to a protected route I get a req.user undefined message.
Frontend Axios call:
export const getData = async (url) => {
console.log('not called?')
try {
const config = {
withCredentials: true,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'backend',
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE'
}
}
const response = await axios.get(url, config);
console.log('response? ', response)
return {
data: response.data,
error: "",
success: true,
};
} catch (exp) {
return {
success: false,
error: exp.response.data,
}
}
}
Backend Protected Route:
router.get("/new-protected", passport.authorize('local', { failureRedirect: '/login' }), (req, res) => {
console.log('whats request?', req.user)
res.send(`Hello, logged in`);
})
When trying this I remove the middleware to see what req looks like, but I always get undefined req.user, so I'm guessing either I'm supposed to be passing req.user somehow in my axios call or I'm not retrieving a user when logging in initially, any ideas on what I'm doing wrong?
Many thanks
You don't have to do anything about the user's data once you log in with authorization, the passport middleware is here for the job, however we should at least set up the right condition for them to exchange the credential, try to change the setting a bit to see how it go :
this part :
app.use(cors({
origin: //put the EXACT URL you host from Vercel
method: 'GET,PUT,POST,DELETE'
credentials: true,
}))
app.set('trust proxy', 1)
app.use(
session({
secret: "secret",
resave: false,
saveUninitialized: true,
store: MongoStore.create({ mongoUrl: MONGO_URI })
})
);
app.use(express.json()); // optional: you can uninstall bodyParser since express have now his own module so you can just replace with this line.
app.use(passport.initialize());
app.use(passport.session());
and update a bit this part at the frontend Axios call :
const config = {
withCredentials: true,
};
I don't know if you have already the issue in localhost or after deployment, if it sill not working than we may have to fix on the cookie session.

How to set equivalent of fetch's { credentials: "include" } in Redux Toolkit's createApi?

I have an express-react-typescript-redux-passport project where I am using createApi from redux toolkit to call a /getuser api on my backend.
I'm using passport-google-oauth20 strategy to authenticate users, and the user is successfully authenticated.
My issue is that passport js deserializeUser() function is not called (even though the serializeUser() is called, and the user is authenticated using google strategy), so the req.user parameter is not set automatically when the front end sends requests to the back end.
I suspect that deserializeUser isn't being called because the I haven't set axio's { withCredentials: true } (or fetch's {credentials: "include"}) parameter in my createApi endpoint. How can I sent this parameter in RTK's createApi?
How do I specify credentials: include here?
Here is my createApi function
export const userApiSlice = createApi({
reducerPath: "api",
baseQuery: fetchBaseQuery({
baseUrl: "http://localhost:4000",
prepareHeaders(headers) {
return headers;
},
}),
endpoints(builder) {
// debugger;
return {
fetchUser: builder.query<IUser, number | void>({
query: () => {
debugger;
return `/getuser`;
},
}),
};
},
});
Here is my server index.js
import express from "express";
import mongoose from "mongoose";
import cors from "cors";
import session from "express-session";
import passport from "passport";
var GoogleStrategy = require("passport-google-oauth20").Strategy;
import { IGoogleAuthUser } from "./types/authTypes";
const PORT = process.env.PORT || 4000;
require("dotenv").config();
const app = express();
mongoose.connect(process.env.LOCAL_DB_ADDRESS, () => {
console.log("connected to mongoose db");
});
app.use(express.json());
app.use(cors({ origin: "http://localhost:3000", credentials: true }));
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: true,
saveUninitialized: true,
})
);
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser((user: IGoogleAuthUser, done: any) => {
//send a cookie to browser to store user id in session
const { id} = user;
console.log("serializeUser called");
return done(null, id);
});
// why isn't this called???
passport.deserializeUser((userId: string, done: any) => {
//attaches the cookie id from session to req.user
console.log("deserializeUser userId : ", userId);
return done(null, userId);
});
//google strategy
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "/auth/google/callback",
},
function (accessToken: any, refreshToken: any, profile: any, done: any) {
//this is called on succesful authentication with the above Google Stratety
console.log("successful authorization");
done(null, profile);
}
)
);
//when user clicks on 'login with google' /auth/google is hit
app.get(
"/auth/google",
passport.authenticate("google", { scope: ["profile", "email"] }),
(req, res) => {
console.log("/auth/google called"); //this console.log does not get called, not sure why
}
);
app.get(
"/auth/google/callback",
passport.authenticate("google", {
successRedirect: "http://localhost:3000/profile",
failureRedirect: "http://localhost:3000/login",
}),
function (req, res) {
// console.dir(req);
// Successful authentication, redirect home.
console.log("redirect to profile"); //this does get called
res.redirect("http://localhost:3000/profile");
}
);
app.get("/", (req, res) => {
res.send("Hello world.");
});
app.get("/getuser", (req: any, res: any) => {
//req should have user thanks to serializer/deserializer
console.log(req.user); // => returns undefined even after successful authentication
res.send(req.user);
});
app.listen(PORT, () => {
console.log(`Server Started on ${PORT}`);
});
Why isn't deserializeUser() being called??
fetchBaseQuery is just a wrapper around fetch with some extra options.
So it's either
baseQuery: fetchBaseQuery({
baseUrl: "http://localhost:4000",
prepareHeaders(headers) {
return headers;
},
credentials: "include"
}),
or
query: () => {
return { url: `/getuser`, credentials: "include" };
},

PassportJS Express req.user not persisting in Heroku

I am using React and Express. Only the React is hosted on heroku and I am hosting the Express server locally. With Express I am using Passportjs with MongoDB.
The problem is that React clien t works well on local deployment, however once I deploy my React App on Heroku it does not work well propertly. When using my deployed React app, I can register a user but I cannot log in a user. It does not return error and POST("/login") returns "Successfully Authenticated" back to me and when I try to access req.user using axios it returns nothing back when it should be returning the user.
React Code
const getUser = () => {
axios({
method: "GET",
withCredentials: true,
url: "http://localhost:3001/user",
})
.then((res) => {
{
console.log(res.data);
if (res.data.username != null)
setMessage("Welcome " + res.data.username);
}
})
.catch((err) => console.log(err));
};
const loginTheUser = async () => {
await axios({
method: "POST",
data: {
username: username,
password: password,
},
withCredentials: true,
url: "http://localhost:3001/login",
}).then((res) => {
if (res.data === "Successfully Authenticated") {
history.push("/");
}
console.log(res.data);
});
await getUser();
};
Express code
// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
cors({
origin: [
"http://localhost:3000",
"https://my-herokuapp.com",
], // <-- 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.initialize());
app.use(passport.session());
require("./passportConfig")(passport);
//Login
app.post("/login", (req, res, next) => {
passport.authenticate("local", (err, user, info) => {
if (err) throw err;
if (!user) {
console.log("Unsuccessful login");
res.send("Unsuccessful login");
} else {
req.logIn(user, (err) => {
if (err) throw err;
{
console.log("Login success");
res.send("Successfully Authenticated");
}
});
}
})(req, res, next);
});
//Register
app.post("/register", (req, res) => {
User.findOne({ username: req.body.username }, async (err, doc) => {
if (err) throw err;
if (doc) res.send("User Already Exists");
if (!doc) {
const hashedPassword = await bcrypt.hash(req.body.password, 10);
const newUser = new User({
username: req.body.username,
password: hashedPassword,
});
await newUser.save();
res.send("User Created");
}
});
});
//get User
app.get("/user", (req, res) => {
res.send(req.user); // The req.user stores the entire user that has been authenticated inside of it.
});
Passport config
const User = require("./user");
const bcrypt = require("bcryptjs");
const localStrategy = require("passport-local").Strategy;
module.exports = function (passport) {
passport.use(
new localStrategy((username, password, done) => {
User.findOne({ username: username }, (err, user) => {
if (err) throw err;
if (!user) return done(null, false);
bcrypt.compare(password, user.password, (err, result) => {
if (err) throw err;
if (result === true) {
return done(null, user);
} else {
return done(null, false);
}
});
});
})
);
passport.serializeUser((user, cb) => {
cb(null, user.id);
});
passport.deserializeUser((id, cb) => {
User.findOne({ _id: id }, (err, user) => {
const userInformation = {
username: user.username,
};
cb(err, userInformation);
});
});
};

Expressjs can not set cookie in the frontend of reactjs after authorization by bcrypt

i am using reactjs to create a online shopping web, and use express js to do backend, when i authorize user login, i can not set cookie to the front end
controller/user/login from expressjs
// user.controller
bcrypt.compare(req.body.password, user[0].password, (err, result) => {
if (err) {
console.log(err);
return res.status(401).json({ message: "password problem" });
}
if (result) {
const userId = JSON.stringify(user[0]._id);
res.cookie('userId', userId, { httpOnly: true, secure: true });
return res.status(200)
.json({
message: userId
})
}
return res.status(401).json({ message: "Auth failed" });
})
app.js from express
const express = require('express');
const app = express();
const morgan = require('morgan');
const bodyPaser = require('body-parser');
const mongoose = require('mongoose');
const cookiePareser = require('cookie-parser');
const cors = require('cors');
const productRouter = require('./api/routes/products');
const orderRouter = require('./api/routes/orders');
const userRouter = require('./api/routes/user');
mongoose.connect("mongodb+srv://conor_9tails:Mongoatlas123#cluster0-xcpy1.mongodb.net/test?retryWrites=true&w=majority",
{
useUnifiedTopology: true
}
);
mongoose.Promise = global.Promise;
mongoose.connection.on('connected', () => {
console.log("connected to mongo atlas");
});
app.use(morgan('dev'));
app.use(cookiePareser());
// app.use('/uploads', express.static('uploads'));
app.use(bodyPaser.urlencoded({ extended: false }));
app.use(bodyPaser.json());
app.use(cors({ origin: "*" }));
app.use('/products', productRouter);
app.use('/orders', orderRouter);
app.use('/user', userRouter);
app.use((req, res, next) => {
const error = new Error('Not found');
error.status = 404;
next(error);
});
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
module.exports = app;
then i make an middleware called auth normally just print out the cookie userId
check-auth.js from middleware/checkauth from expressjs
module.exports.requireAuth = (req, res, next) => {
console.log("THIS IS cookies", req.cookies);
next();
};
from the front end, i create a login component from reactjs
handleSubmit(event) {
let { email, password } = this.state;
fetch("http://localhost:5000/user/login", {
method: "POST",
body: JSON.stringify({
email, password
}),
headers: {
"content-type": "application/json; charset=UTF-8"
}
})
.then(response => {
return response.json();
})
.then((json) => {
console.log(json);
})
.catch((error) => {
console.log(error);
})
event.preventDefault();
}
as you can see i console.log response.json() which contain message of userId and it succeeded enter image description here
but there is no cookie was stored in the Application of Chrome
Thank you for your time to help me tackle with this daunting problem

Resources