I am having trouble identifying why exactly my session id is not being set in my expressjs backend api.
When I run Postman via a post request to /provision
:
const express = require("express");
require("express-async-errors");
const cors = require("cors");
const cookieSession = require("cookie-session");
const createTables = require("./queries/create-tables");
const keys = require("./keys");
const cleanup = require("./queries/cleanup");
const app = express();
app.set("trust proxy", "127.0.0.1");
app.use(
cors({
origin:
process.env.NODE_ENV === "production"
? ["<some-domain>", "<some-domain>"]
: ["http://localhost:3000"],
credentials: true,
})
);
app.use(express.json());
app.use(
cookieSession({
secure: process.env.NODE_ENV === "production",
keys: [keys.cookieKey],
sameSite: "Lax",
httpOnly: true,
domain: "<some-domain>",
})
);
app.use((req, res, next) => {
console.log("Session:", req.session);
if (!req.session) {
return next(new Error("Session is not set up properly"));
}
next();
});
app.post("/provision", require("./provision"));
app.post("/query", require("./query"));
app.post("/reset", require("./reset"));
It appears to successfully run the provision.js logic:
const pool = require("./pool");
const createRole = require("./queries/create-role");
const createDb = require("./queries/create-db");
const { createId, validateId } = require("./queries/id");
module.exports = async (req, res) => {
let id = req.session.id;
if (!id) {
id = createId(8);
req.session.id = id;
}
validateId(id);
try {
await createRole(id);
await createDb(id);
res.send({ status: "ok" });
} catch (err) {
console.error(err);
throw new Error("Failed to provision db");
}
};
But when I go to run a post request on /query
with the following query:
{
"query": "SELECT * FROM users WHERE id = 1"
}
I get:
{
"error": "Session ID is missing"
}
After verifying session middleware is correct, the session handling appears correct, but why is the session id still not being set?
This is the code inside of query.js:
const createClient = require("./queries/create-client");
const { validateId } = require("./queries/id");
const dbExists = require("./queries/db-exists");
const touchLogin = require("./queries/touch-login");
module.exports = async (req, res) => {
const { id } = req.session;
console.log("Session:", id);
if (!id) {
return res.status(400).json({ error: "Session ID is missing" });
}
validateId(id);
if (!(await dbExists(id))) {
throw new Error("No database found. Reload this page.");
}
await touchLogin(id);
const client = await createClient(id);
try {
console.log("Query:", req.body.query);
const result = await client.query(req.body.query);
if (Array.isArray(result)) {
res.send(
result.map(({ rows, fields, command, rowCount }) => ({
command,
rows,
fields,
rowCount,
}))
);
} else {
res.send([
{
command: result.command,
rows: result.rows,
fields: result.fields,
rowCount: result.rowCount,
},
]);
}
} catch (err) {
console.error("Query Execution Error:", err);
res.status(500).json({ error: err.message });
} finally {
await client.end();
}
};
So I have @WeDoTheBest4You to thank for helping me arrive at my solution. So because the domain names I am using do not actually exist yet and yet I have these domains If the domains do not exist, the user agent will fail to resolve the domain names, leading to errors when attempting to connect to those servers. As a result, the user agent won't even reach the point where cookies could be set or sent:
{
"query": "SELECT * FROM users WHERE id = 1"
}
If I do not have a crystal clear understanding of it, please someone feel free to edit my solution or comment and I will edit it accordingly.
The solution was to refactor my index.js file to the following:
const allowedOrigins =
process.env.NODE_ENV === "production"
? ["<some-domain>", "<some-other-domain>"]
: ["http://localhost:3000"];
app.set("trust proxy", process.env.NODE_ENV === "production" ? 1 : 0);
app.use(
cors({
origin: function (origin, callback) {
if (!origin) {
return callback(null, true);
}
if (allowedOrigins.indexOf(origin) === -1) {
const msg =
"The CORS policy for this site does not allow access from the specified origin";
return callback(new Error(msg), false);
}
return callback(null, true);
},
credentials: true,
})
);
// app.use(
// cors({
// origin:
// process.env.NODE_ENV === "production"
// ? ["<some-domain>", "<some-other-domain>"]
// : ["http://localhost:3000"],
// credentials: true,
// })
// );
app.use(express.json());
app.use(
cookieSession({
secure: process.env.NODE_ENV === "production",
keys: [keys.cookieKey],
sameSite: "Lax",
httpOnly: true,
domain: process.env.NODE_ENV === "production" ? "<some-domain>" : undefined,
})
);
And this worked. Now the API is still not working in that now I am getting a different error, but this error has now been resolved. Thanks again.