From 23a39247a12fdce4dc1e1c054a85ea863b9a6585 Mon Sep 17 00:00:00 2001 From: Fredrik Wahlberg Date: Fri, 24 Jan 2025 22:02:54 +0100 Subject: [PATCH] Implement session-based authentication and add logout functionality Fix #15 --- middleware/auth.js | 9 ++---- package-lock.json | 72 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + public/app.js | 14 +++++---- routes/auth.js | 10 +++++++ server.js | 10 +++++++ 6 files changed, 104 insertions(+), 12 deletions(-) diff --git a/middleware/auth.js b/middleware/auth.js index 2ed8e42..db01305 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -1,15 +1,10 @@ const basicAuth = require('basic-auth'); const auth = (req, res, next) => { - const user = basicAuth(req); - const username = process.env.AUTH_USERNAME; // Use environment variables - const password = process.env.AUTH_PASSWORD; // Use environment variables - - if (user && user.name === username && user.pass === password) { + if (req.session && req.session.user) { return next(); } else { - res.set('WWW-Authenticate', 'Basic realm="401"'); - return res.status(401).send('Authentication required.'); + res.status(401).send('Authentication required.'); } }; diff --git a/package-lock.json b/package-lock.json index 92dfda1..dc98d75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "debug": "^4.4.0", "dotenv": "^16.4.7", "express": "^4.21.2", + "express-session": "^1.18.1", "fs": "^0.0.1-security" } }, @@ -308,6 +309,50 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-session": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.1.tgz", + "integrity": "sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -584,6 +629,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -623,6 +676,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -828,6 +889,17 @@ "node": ">= 0.6" } }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index 489b9f0..0c92731 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "debug": "^4.4.0", "dotenv": "^16.4.7", "express": "^4.21.2", + "express-session": "^1.18.1", "fs": "^0.0.1-security" } } diff --git a/public/app.js b/public/app.js index 9cf6556..c31c51e 100644 --- a/public/app.js +++ b/public/app.js @@ -17,11 +17,15 @@ document.addEventListener('DOMContentLoaded', function() { const loginMessage = document.getElementById('loginMessage'); // Check if user is already logged in - if (sessionStorage.getItem('loggedIn') === 'true') { - loginContainer.style.display = 'none'; - appContainer.style.display = 'block'; - loadTags(); - } + fetch('/check-session') + .then(response => response.json()) + .then(data => { + if (data.loggedIn) { + loginContainer.style.display = 'none'; + appContainer.style.display = 'block'; + loadTags(); + } + }); loginForm.addEventListener('submit', function(e) { e.preventDefault(); diff --git a/routes/auth.js b/routes/auth.js index 287a388..1827016 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -8,10 +8,20 @@ router.post('/login', (req, res) => { const password = process.env.AUTH_PASSWORD; if (user && user.name === username && user.pass === password) { + req.session.user = user.name; res.status(200).send('Login successful'); } else { res.status(401).send('Authentication required'); } }); +router.post('/logout', (req, res) => { + req.session.destroy((err) => { + if (err) { + return res.status(500).send('Error logging out'); + } + res.status(200).send('Logout successful'); + }); +}); + module.exports = router; \ No newline at end of file diff --git a/server.js b/server.js index 5b74e2f..636adb1 100644 --- a/server.js +++ b/server.js @@ -1,6 +1,7 @@ require('dotenv').config(); const express = require('express'); const bodyParser = require('body-parser'); +const session = require('express-session'); const debug = require('debug')('app'); const tasksRouter = require('./routes/tasks'); const authRouter = require('./routes/auth'); @@ -10,6 +11,15 @@ const port = 3044; app.use(bodyParser.json()); app.use(express.static('public')); + +// Configure session middleware +app.use(session({ + secret: process.env.SESSION_SECRET || 'default_secret', // Use a strong secret in production + resave: false, + saveUninitialized: true, + cookie: { secure: false } // Set to true if using HTTPS +})); + app.use('/', tasksRouter); app.use('/', authRouter);