ReactJS Express-Session Integration with CORS

18 Views Asked by At

Here I am trying to integrate session handling in a ReactJS application with express-server back-end. However, Inspite of all the suggestions available out their in all of the forums and communities, I am not able to receive the session cookie on the client (ReactJS).

React client is running on http://localhost:5173 and Express server is running on http://localhost:3001

Here is my 'app.ts' (express-server configuration setup)

export const MemoryStore = require("memorystore")(session);
export const sessionStore = new MemoryStore({
  checkPeriod: 3600000, // prune expired entries every 24h
});

export const app = express();
app.use(morgan("dev"));
app.use(json());

app.use(
  cors({
    origin: ["http://localhost:5173","http://localhost:3001"],
    methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    credentials: true,
    exposedHeaders: ["set-cookie"],
  })
);

app.use((req, res, next) => {
  res.header("Access-control-Allow-Origin", "http://localhost:5173");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept, Authorization, set-cookie"
  );
  res.header("Access-Control-Allow-Credentials", 'true');
  if (req.method === "OPTIONS") {
    res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET");
    return res.status(200).json({});
  }
  next();
});

app.use(
  session({
    name: "react_session",
    secret: "react_session_key",
    resave: false,
    saveUninitialized: false,
    store: sessionStore,
    cookie: {
      httpOnly: true,
      maxAge: 3600000,
      sameSite: "lax",
      secure: false,
      domain: 'localhost'
    },
  })
);

app.use(authRouter);
app.listen(3001, () => console.log(`server is running`));

I have successfully implemented Google Authentication for ReactJS app and upon receiving the ID token from Auth server, I would like to populate the session.user attribute with the email value from token.

The API endpoints in Express-server performing authentication job are implemented as follows :


authRouter.post("/api/auth/google", async (req: Request, res: Response) => {
  const { tokens } = await oAuth2Client.getToken(atob(req.body.code)); // exchange code for tokens

  // Explicitly set cookie is correctly received by the client.
  
  /*res.cookie("react_token", JSON.stringify(req.session.id), {
    maxAge: 1000 * 60 * 60,
    httpOnly: false,
    secure: false,
    domain: "localhost",
  });*/
  
  console.log(
    `session id user session [id = ${req.session.id} ] ` +
      JSON.stringify(req.cookies)
  );

  // Following line prints new session id for each request. This means the session is created on the server
  // But no set-cookie response header is sent back to the client.
  sessionStore.all((error: Error, sessions: any) => {});

  res.json(tokens);
});

authRouter.get(
  "/api/auth/checksession",
  async (req: Request, res: Response) => {
    console.log(
      `session id user session [id = ${req.session.id} ] ` +
        JSON.stringify(req.cookies)
    );
    sessionStore.all((error: Error, sessions: any) => {});
    res.send({ sessionId: req.session.id });
  }
);

From React JS client application, after receiving a successful token response from "/api/auth/google", I am immediately issuing 2 http requests to a dummy 'checksession' endpoint one after another to prove the existence of a persistent session across requests. Unfortunately, for each request to '/checksession' endpoint, a new 'sessionId' value is printed.

In my React Client app,


fetch("http://localhost:3001/api/auth/checksession", {
            method: "GET",
            credentials : "include",
            mode: "cors",
            headers: {
              "Content-Type": "application/json",
            },
          }).then((response) => {
            
            // UNABLE TO RECIEVE ANY SESSION COOKIE HERE
            // HOWEVER any custom cookie sent by server is received here.   
            console.log('document cookies USER AUTH === ' + document.cookie)
            console.log('response headers for USER AUTH === ' + response.headers.getSetCookie());
          });
          

Honesly, I have tried all combinations of 'secure:true/false', 'samesite:none/lax', but nothing seem to be working.

Any help will be much appreciated.

0

There are 0 best solutions below