diff --git a/Sean/server.js b/Sean/server.js
index 8dd5cce..46eb2e6 100644
--- a/Sean/server.js
+++ b/Sean/server.js
@@ -19,32 +19,19 @@ const PORT = process.env.PORT || 3000;
require("dotenv").config();
app.use(bodyParser.urlencoded({ extended: true }));
-app.use(
- session({
- secret: process.env.key,
- resave: false,
- saveUninitialized: true,
- cookie: {
- secure: false, // Make sure to set this to true in a production environment with HTTPS
- httpOnly: true,
- maxAge: 24 * 60 * 60 * 1000, // Session duration in milliseconds (here set to 1 day)
- },
- })
-);
-
-app.use((req, res, next) => {
- if (!req.session.csrfToken) {
- req.session.csrfToken = crypto.randomBytes(32).toString('hex');
- }
-
- // Make the CSRF token available in the response context
- res.locals.csrfToken = req.session.csrfToken;
- console.log(`Server-side CSRF Token: ${req.session.csrfToken}`);
- next();
-});
app.set("view engine", "ejs");
+app.use(session({
+ secret: process.env.key,
+ resave: false,
+ saveUninitialized: true,
+ cookie: {
+ secure: false, // Make sure to set this to true in a production environment with HTTPS
+ httpOnly: true,
+ maxAge: 24 * 60 * 60 * 1000, // Session duration in milliseconds (here set to 1 day)
+ },
+}));
function isAuthenticated(req, res, next) {
if (req.session && req.session.authenticated) {
return next();
@@ -144,17 +131,11 @@ const logActivity = async (username, success, message) => {
app.post('/login', [
body('username').escape().trim().isLength({ min: 1 }).withMessage('Username must not be empty'),
body('password').escape().trim().isLength({ min: 1 }).withMessage('Password must not be empty'),
- body('csrf_token').escape().trim().isLength({ min: 1 }).withMessage('CSRF token must not be empty'),
],
async (req, res) => {
try {
const errors = validationResult(req);
- // Validate CSRF token
- if (req.body.csrf_token !== req.session.csrfToken) {
- return res.status(403).send("Invalid CSRF token");
- }
-
if (!errors.isEmpty()) {
// Handle validation errors, e.g., return an error message to the client
return res.render('login', { error: 'Invalid input. Please check your credentials.', csrfToken: req.session.csrfToken });
@@ -222,17 +203,11 @@ async (req, res) => {
// OTP verification route
app.post("/verify-otp", [
body('otp').escape().trim().isLength({ min: 1 }).withMessage('OTP must not be empty'),
- body('csrf_token').escape().trim().isLength({ min: 1 }).withMessage('CSRF token must not be empty'),
],
async (req, res) => {
try {
const errors = validationResult(req);
- // Validate CSRF token
- if (req.body.csrf_token !== req.session.csrfToken) {
- return res.status(403).send("Invalid CSRF token");
- }
-
if (!errors.isEmpty()) {
// Handle validation errors, e.g., return an error message to the client
return res.render('otp', { error: 'Invalid OTP. Please try again.', username: req.body.username, csrfToken: req.session.csrfToken });
@@ -240,10 +215,16 @@ async (req, res) => {
const enteredOTP = req.body.otp;
+ if (!req.session) {
+ // If session is not defined, handle accordingly
+ console.error("Session is not defined.");
+ return res.status(500).send("Internal Server Error");
+ }
+
if (enteredOTP === req.session.otp) {
- // Log successful OTP entry and login
+ // Log successful OTP entry
if (req.body.username) {
- await logActivity(req.body.username, true, "OTP entered correctly. Successful login");
+ await logActivity(req.body.username, true, "OTP entered correctly");
}
// Correct OTP, generate a session token
@@ -253,8 +234,22 @@ async (req, res) => {
req.session.authenticated = true;
req.session.username = req.body.username;
req.session.sessionToken = sessionToken;
- res.locals.csrfToken = req.session.csrfToken;
- console.log(`Server-side CSRF Token: ${req.session.csrfToken}`);
+
+ // Generate and store anti-CSRF token in the session
+ req.session.csrfToken = crypto.randomBytes(32).toString('hex');
+
+ // Set anti-CSRF token in res.locals
+ res.locals.csrfToken = req.session.csrfToken;
+
+ // Log anti-CSRF token
+ console.log(`Generated Anti-CSRF Token: ${req.session.csrfToken}`);
+
+ // Implement secure session handling:
+ // 1. Set secure, HttpOnly, and SameSite flags
+ // 2. Set an expiration time for the session token
+ // 3. Regenerate the session after authentication
+ res.cookie('sessionToken', sessionToken, { secure: true, httpOnly: true, expires: new Date(Date.now() + 24 * 60 * 60 * 1000) }); // Expires in 1 day
+
console.log(`Generated Session Token: ${sessionToken}`);
// Redirect to home page with session token
@@ -273,7 +268,9 @@ async (req, res) => {
res.status(500).send("Internal Server Error");
}
});
-
+
+
+
app.get("/logout", (req, res) => {
try {
const username = req.session.username || "Unknown User";
diff --git a/Sean/views/inusers.ejs b/Sean/views/inusers.ejs
index 6109a16..05a6c24 100644
--- a/Sean/views/inusers.ejs
+++ b/Sean/views/inusers.ejs
@@ -146,6 +146,7 @@
diff --git a/Sean/views/inusers.js b/Sean/views/inusers.js
index 32caea6..a92b225 100644
--- a/Sean/views/inusers.js
+++ b/Sean/views/inusers.js
@@ -1,6 +1,5 @@
-
$(document).ready(function () {
$('#resetPasswordLink').on('click', function () {
$('#resetPasswordFormContainer').show();
@@ -429,5 +428,7 @@ $('#resetPasswordForm').on('submit', function (e) {
});
});
+
+
diff --git a/Sean/views/login.ejs b/Sean/views/login.ejs
index 2c4428f..ec63272 100644
--- a/Sean/views/login.ejs
+++ b/Sean/views/login.ejs
@@ -86,7 +86,6 @@ button:hover {
-
diff --git a/Sean/views/otp.ejs b/Sean/views/otp.ejs
index 64df4ef..1966179 100644
--- a/Sean/views/otp.ejs
+++ b/Sean/views/otp.ejs
@@ -69,7 +69,7 @@
-
+