Encrypt cookies, set them to expire at the end of time, httpOnly and sameSite as good security practices

This commit is contained in:
Rogerio Chaves 2020-04-20 21:19:57 +02:00
parent b6e8242bb6
commit b7cb6f69e7
No known key found for this signature in database
GPG Key ID: E6AF5440509B1D94
3 changed files with 23 additions and 7 deletions

View File

@ -24,6 +24,7 @@ const Sentry = require("@sentry/node");
const metrics = require("./metrics"); const metrics = require("./metrics");
const sgMail = require("@sendgrid/mail"); const sgMail = require("@sendgrid/mail");
const ejs = require("ejs"); const ejs = require("ejs");
const cookieEncrypter = require("cookie-encrypter");
let ssbServer; let ssbServer;
let mode = process.env.MODE || "client"; let mode = process.env.MODE || "client";
@ -75,8 +76,17 @@ app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.urlencoded({ extended: true }));
app.set("view engine", "ejs"); app.set("view engine", "ejs");
app.use(express.static("public")); app.use(express.static("public"));
app.use(cookieParser());
app.use(fileUpload()); app.use(fileUpload());
const cookieSecret =
process.env.COOKIES_SECRET || "set_cookie_secret_you_are_unsafe"; // has to be 32-bits
const cookieOptions = {
httpOnly: true,
signed: true,
expires: new Date(253402300000000), // Friday, 31 Dec 9999 23:59:59 GMT, nice date from stackoverflow
sameSite: true,
};
app.use(cookieParser(cookieSecret));
app.use(cookieEncrypter(cookieSecret));
app.use(async (req, res, next) => { app.use(async (req, res, next) => {
if (!ssbServer) { if (!ssbServer) {
setTimeout(() => { setTimeout(() => {
@ -93,7 +103,7 @@ app.use(async (req, res, next) => {
res.locals.context = req.context; res.locals.context = req.context;
try { try {
const identities = await ssbServer.identities.list(); const identities = await ssbServer.identities.list();
const key = req.cookies["ssb_key"]; const key = req.signedCookies["ssb_key"];
if (!key) return next(); if (!key) return next();
const parsedKey = JSON.parse(key); const parsedKey = JSON.parse(key);
@ -165,7 +175,7 @@ router.post("/login", async (req, res) => {
try { try {
const decodedKey = reconstructKeys(submittedKey); const decodedKey = reconstructKeys(submittedKey);
res.cookie("ssb_key", JSON.stringify(decodedKey)); res.cookie("ssb_key", JSON.stringify(decodedKey), cookieOptions);
decodedKey.private = "[removed]"; decodedKey.private = "[removed]";
debug("Login with key", decodedKey); debug("Login with key", decodedKey);
@ -210,7 +220,7 @@ router.post("/signup", async (req, res) => {
debug("Created new user with id", profileId); debug("Created new user with id", profileId);
res.cookie("ssb_key", JSON.stringify(key)); res.cookie("ssb_key", JSON.stringify(key), cookieOptions);
key.private = "[removed]"; key.private = "[removed]";
debug("Generated key", key); debug("Generated key", key);
@ -234,7 +244,7 @@ router.post("/signup", async (req, res) => {
router.get("/keys", (req, res) => { router.get("/keys", (req, res) => {
res.render("keys", { res.render("keys", {
useEmail: process.env.SENDGRID_API_KEY, useEmail: process.env.SENDGRID_API_KEY,
key: req.cookies["ssb_key"], key: req.signedCookies["ssb_key"],
}); });
}); });
@ -244,7 +254,7 @@ router.post("/keys/email", async (req, res) => {
let html = await ejs.renderFile("views/email_sign_in.ejs", { let html = await ejs.renderFile("views/email_sign_in.ejs", {
origin, origin,
ssb_key: req.cookies["ssb_key"], ssb_key: req.signedCookies["ssb_key"],
}); });
sgMail.setApiKey(process.env.SENDGRID_API_KEY); sgMail.setApiKey(process.env.SENDGRID_API_KEY);
@ -260,7 +270,7 @@ router.post("/keys/email", async (req, res) => {
}); });
router.get("/keys/copy", (req, res) => { router.get("/keys/copy", (req, res) => {
res.render("keys_copy", { key: req.cookies["ssb_key"] }); res.render("keys_copy", { key: req.signedCookies["ssb_key"] });
}); });
router.get("/keys/download", async (req, res) => { router.get("/keys/download", async (req, res) => {

5
app/package-lock.json generated
View File

@ -740,6 +740,11 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
}, },
"cookie-encrypter": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cookie-encrypter/-/cookie-encrypter-1.0.1.tgz",
"integrity": "sha512-T0EPLKs2vwyaJyRIs3oZ3B/52ny3e09KK+JiMf/6orthjFYCPPX+L8ahlYlipUjIf+ZfXvC0RqDCrxqRRFa05A=="
},
"cookie-parser": { "cookie-parser": {
"version": "1.4.5", "version": "1.4.5",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz",

View File

@ -17,6 +17,7 @@
"@sendgrid/mail": "^7.0.1", "@sendgrid/mail": "^7.0.1",
"@sentry/node": "^5.15.4", "@sentry/node": "^5.15.4",
"chokidar": "^3.3.1", "chokidar": "^3.3.1",
"cookie-encrypter": "^1.0.1",
"cookie-parser": "^1.4.5", "cookie-parser": "^1.4.5",
"debug": "^4.1.1", "debug": "^4.1.1",
"ejs": "^3.0.2", "ejs": "^3.0.2",