Dr. Greg M. Bernstein
Update October 19th, 2021
express-session
1Express Middleware to help us:
express-session
2Uses other packages for:
request
parameter for easy use by our software.Example files in: SessionJSONExample.zip. Start of a tour company JSON API
/tours
, GET: returns list of tours in JSON/login
, POST: takes email and password, returns user info/logout
, GET: ends the session/addTour
, POST: takes tour data, only admin usersFrom tourServer.mjs
import express from 'express';
const app = express();
import session from 'express-session';
import bcrypt from 'bcryptjs';
const cookieName = "TourSid"; // Session ID cookie name, use this to delete cookies too.
app.use(session({
secret: 'website development CSUEB',
resave: false,
saveUninitialized: false,
name: cookieName // Sets the name of the cookie used by the session middleware
}));
// Fake user and tour data
import { readFile } from 'fs/promises';
const users = JSON.parse(await readFile(new URL('./secUsers.json',
import.meta.url)));
const tours = JSON.parse(await readFile(new URL('./tours.json',
import.meta.url)));
From tourServer.mjs
, uses middleware
// This initializes session state
function setUpSessionMiddleware(req, res, next) {
console.log(`\nsession object: ${JSON.stringify(req.session)}`);
console.log(`session id: ${req.session.id}`);
if (!req.session.user) {
req.session.user = { role: "guest" };
};
next();
};
app.use(setUpSessionMiddleware);
From tourServer.mjs
// Use this middleware to restrict paths to only logged in users
function checkCustomerMiddleware(req, res, next) {
if (req.session.user.role === "guest") {
res.status(401).json({ error: "Not permitted" });;
} else {
// console.log(`\nSession info: ${JSON.stringify(req.session)} \n`);
next();
}
};
// Use this middleware to restrict paths only to admins
function checkAdminMiddleware(req, res, next) {
if (req.session.user.role !== "admin") {
res.status(401).json({ error: "Not permitted" });;
} else {
next();
}
};
From tourServer.mjs
// Only available to admin, returns updated tour list.
app.post('/addTour', checkAdminMiddleware, express.json(), function(req, res) {
let temp = req.body;
// console.log(temp);
// Note need to check input here to prevent injection attacks
let event = {
name: temp.name,
date: temp.date,
};
tours.virtTours.push(event);
res.json(tours.virtTours);
});
From tourServer.mjs
// Available to all visitors, returns user info if successful
app.post('/login', express.json(), function(req, res) {
let email = req.body.email;
let password = req.body.password;
// Find user
let auser = users.find(function(user) {
return user.email === email
});
if (!auser) { // Not found
res.status(401).json({ error: true, message: "User/Password error" });
return;
}
let verified = bcrypt.compareSync(password, auser.passHash);
if (verified) {
// Upgrade in priveledge, should generate new session id
// Save old session information if any, create a new session
let oldInfo = req.session.user;
req.session.regenerate(function(err) {
if (err) {
console.log(err);
}
let newUserInfo = Object.assign(oldInfo, auser);
delete newUserInfo.passHash;
req.session.user = newUserInfo;
res.json(newUserInfo);
});
} else {
res.status(401).json({ error: true, message: "User/Password error" });
}
});
Using a Node.js program, addTourTest.mjs
/* Testing the POST /tours/add API */
import fetch from "node-fetch";
import urlBase from './testURL.mjs';
function extractCookies(rawStrings) {
let cookies = [];
rawStrings.forEach(function(ck) {
cookies.push(ck.split(";")[0]); // Just grabs cookie name=value part
});
return cookies.join(";"); // If more than one cookie join with ;
}
let addTour = {
url: urlBase + "addTour",
options: {
method: "POST",
body: JSON.stringify({
name: "Windsurf K2-18b, 110 Light Years",
date: "Sometime in 2025",
}),
headers: { "Content-Type": "application/json" },
},
};
let loginAdmin = {
url: urlBase + "login",
options: {
method: "POST",
body: JSON.stringify({
// admin user, see users.json file
email: "antisun1921@outlook.com",
password: "R.r<E&xt",
}),
headers: { "Content-Type": "application/json" },
},
};
let loginCust = {
url: urlBase + "login",
options: {
method: "POST",
body: JSON.stringify({
// admin user, see users.json file
email: "stedhorses1903@yahoo.com",
password: "nMQs)5Vi",
}),
headers: { "Content-Type": "application/json" },
},
};
async function someTests() {
console.log("Try adding tour without logging in");
try {
let res = await fetch(addTour.url, addTour.options);
console.log(`Add Tour result: ${res.statusText}`);
} catch (e) {
console.log(`Error: ${e}\n`);
}
console.log("Login as admin, then adding tour");
try {
let res = await fetch(loginAdmin.url, loginAdmin.options);
console.log(`login results: ${res.statusText}`);
// Look at the cookie
let savedCookie = extractCookies(res.headers.raw()["set-cookie"]);
console.log(`Saved cookie: ${savedCookie}`);
addTour.options.headers.cookie = savedCookie;
// User info from login
let userInfo = await res.json();
console.log(userInfo);
res = await fetch(addTour.url, addTour.options);
console.log(`Add Tour result: ${res.statusText}\n`);
let data = await res.json();
console.log(data);
} catch (e) {
console.log(`Error: ${e}\n`);
}
console.log("Login as customer, then try adding tour");
try {
let res = await fetch(loginCust.url, loginCust.options);
console.log(`login results: ${res.statusText}`);
// Look at the cookie
let savedCookie = extractCookies(res.headers.raw()["set-cookie"]);
console.log(`Saved cookie: ${savedCookie}`);
addTour.options.headers.cookie = savedCookie;
// User info from login
let userInfo = await res.json();
console.log(userInfo);
res = await fetch(addTour.url, addTour.options);
console.log(`Add Tour result: ${res.statusText}\n`);
let data = await res.json();
console.log(data);
} catch (e) {
console.log(`Error: ${e}\n`);
}
}
someTests();
From tourServer.mjs
app.get('/logout', function (req, res) {
let options = req.session.cookie;
req.session.destroy(function (err) {
if (err) {
console.log(err);
}
res.clearCookie(cookieName, options); // the cookie name and options
res.json({message: "Goodbye"});
})
});