Search code examples
node.jsexpresses6-modulesexpress-session

Why is express-mysql-session writing to the database, but somehow not reading from it?


I've got a nodejs app written with ECMA syntax, with a dependencies.mjs and index.js. I think I have got the express-mysql-session and express-session set up right, as I've got it going before with a previous commonJS project, but this weird behaviour is doing my head in.

The relevant code in index.js:

'use strict';
import dotenv from 'dotenv';
dotenv.config();
import dependencies from "./dependencies.mjs";
const { DateTime, express, connectToDb, cors, mysql2 } = dependencies;
import session from "express-session";
import MySQLStore from "express-mysql-session";

const sessconn = mysql2.createPool({
  host: process.env.SESSION_DB_HOST,
  user: process.env.SESSION_DB_USER,
  password: process.env.SESSION_DB_PASSWORD,
  database: process.env.SESSION_DB_NAME,
  socketPath: process.env.SOCKET_PATH,
  connectionLimit: 1,
});

const sessionStore = new (MySQLStore(session))({
  clearExpired: true,
  expiration: 86400000,
    checkExpirationInterval: 3600000,
  createDatabaseTable: true,
    }, 
  sessconn);
    
    connectToDb().then(()=>{
      console.log('connected to db!!');
    }
    ).catch((err)=>{
        return res.status(500).send({msg: 'Error connecting to database', err: err.message})
    })

const app = express();
app.use(express.json({ limit: '300kb' }))
app.use(cors({
  origin: process.env.WEBSITE_DOMAIN,
  allowedHeaders: ["content-type", "authorization"],
  credentials: true,
}));
app.use(session({
  name: 'session_name',
  store: sessionStore,
  secret: process.env.SESSION_SECRET,
  saveUninitialized: false,
  resave: false,
  cookie: {
    sameSite: 'none',
    secure: false
    maxAge: +process.env.COOKIE_MAXAGE,
    httpOnly: true,
  }
}));

  app.use(express.static('public'));

  import { router as authRoutes } from './routes/auth.mjs';
app.use('/auth', authRoutes)

// auth middleware / login wall
app.use((req,res,next) => {
  if (req.session.user) {
    let expiry = DateTime.now().plus({hours: 1}).toISO();
    req.session.user.expiry = expiry;
    next();
  } else {
    res.status(403).send({ msg: "You must be logged in to access this resource."});
  }
})
  app.listen(port, () => console.log(`Its alive on port ${port}!`))

and my dependencies.mjs

"use strict";
import dotenv from 'dotenv';
dotenv.config();
import express from 'express';
import cors from 'cors';
import { DateTime, Settings } from 'luxon';
Settings.defaultZone = "Australia/Brisbane";
import validation from 'express-validator';
const { body, validationResult, param, check } = validation;
import mysql2 from 'mysql2/promise';

const dbconn = await mysql2.createConnection({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  socketPath: process.env.SOCKET_PATH,
});

async function connectToDb() {
  try {
    await dbconn.connect()
  } catch (err) {
    return err
  }
}

import bcrypt from 'bcrypt'
import crypto from 'crypto'
import sgMail from '@sendgrid/mail';
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

export default { 
  DateTime, 
  Settings, 
  express, 
  body,
  check,
  param,
  validationResult, 
  dbconn, 
  bcrypt, 
  crypto, 
  sgMail, 
  cors,
  connectToDb,
  mysql2
};

I have an auth route, where I set the session up once the user logs in:

if(req.session.user){
            return res.status(200).send({msg: "Logged in already.", user: req.session.user});
        } else {
            const expireTime = DateTime.now().plus({hours: 1}).toISO();
            req.session.cookie.user = {
                id: user_object.id,
                email: req.body.username,
                name: `${first} ${last}`,
                expiry: expireTime
            }

            return res.status(200).send({msg: "Session created", user: req.session.user});
        } 

This saves a record in the correct table in the correct database. The record looks correct, I just check it by accessing mysql via the terminal to check it's there.

When I call a route below the login wall however, it returns a different session than the one I had written to the database. I have no idea why, and I've done my best to stick to the book in implementing this. Any help would be greatly appreciated!

(ChatGPT, bless its heart, couldn't help much either, and I have had no luck finding a similar problem by googling).


Solution

  • Facepalm moment, but worth sharing.

    Basically everything in the backend was fine. I've changed a few things since posting but I believe this would have worked nonetheless.

    I was not sending my api call with "credentials" ie not sending the cookie. This resulted in a new session being created with each call.

    Using "withCredentials: true" in the api call solved the issue.