104 lines
2.5 KiB
JavaScript
104 lines
2.5 KiB
JavaScript
/**
|
|
* Authentication Middleware for Weight Tracker
|
|
* Handles password protection and session management
|
|
*/
|
|
|
|
const bcrypt = require('bcryptjs');
|
|
const session = require('express-session');
|
|
const cookieParser = require('cookie-parser');
|
|
|
|
// Default session configuration
|
|
const sessionConfig = {
|
|
secret: process.env.SESSION_SECRET || 'weight-tracker-secret',
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
cookie: {
|
|
secure: process.env.COOKIE_SECURE === 'true',
|
|
httpOnly: true,
|
|
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Initialize authentication middleware
|
|
* @param {Object} app - Express app
|
|
*/
|
|
function initAuth(app) {
|
|
// Parse cookies
|
|
app.use(cookieParser());
|
|
|
|
// Session management
|
|
app.use(session(sessionConfig));
|
|
|
|
// Serve login page
|
|
app.get('/login', (req, res) => {
|
|
if (req.session.authenticated) {
|
|
return res.redirect('/');
|
|
}
|
|
res.sendFile('login.html', { root: __dirname });
|
|
});
|
|
|
|
// Handle login form submission
|
|
app.post('/auth/login', (req, res) => {
|
|
const { password } = req.body;
|
|
const storedHash = process.env.PASSWORD_HASH;
|
|
|
|
if (!storedHash) {
|
|
console.error('PASSWORD_HASH environment variable not set');
|
|
return res.redirect('/login?error=config');
|
|
}
|
|
|
|
// Verify password
|
|
bcrypt.compare(password, storedHash, (err, isMatch) => {
|
|
if (err) {
|
|
console.error('Error verifying password:', err);
|
|
return res.redirect('/login?error=server');
|
|
}
|
|
|
|
if (isMatch) {
|
|
// Set session as authenticated
|
|
req.session.authenticated = true;
|
|
res.redirect('/');
|
|
} else {
|
|
res.redirect('/login?error=invalid');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Logout endpoint
|
|
app.get('/auth/logout', (req, res) => {
|
|
req.session.destroy();
|
|
res.redirect('/login');
|
|
});
|
|
|
|
// Authentication middleware for all other routes
|
|
app.use((req, res, next) => {
|
|
// Skip auth for login-related routes
|
|
if (req.path === '/login' || req.path === '/auth/login') {
|
|
return next();
|
|
}
|
|
|
|
// Check if user is authenticated
|
|
if (req.session.authenticated) {
|
|
return next();
|
|
}
|
|
|
|
// Redirect to login page
|
|
res.redirect('/login');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Generate a password hash (utility function)
|
|
* @param {string} password - Plain text password
|
|
* @returns {Promise<string>} - Hashed password
|
|
*/
|
|
function generateHash(password) {
|
|
return bcrypt.hash(password, 10);
|
|
}
|
|
|
|
module.exports = {
|
|
initAuth,
|
|
generateHash
|
|
};
|