feat: Enhance login page security and caching

- Add rate limit handling for PIN verification with user-friendly error message
- Disable PIN input on repeated failed attempts to prevent refresh loops
- Implement cache control headers for login page to prevent browser caching
This commit is contained in:
Greirson Lee-Thorp
2025-02-21 11:08:21 -08:00
parent aa25ef92f8
commit 1a74774d6a
2 changed files with 41 additions and 3 deletions

View File

@@ -209,7 +209,12 @@
// Check PIN length and initialize
fetch('/api/auth/pin-required')
.then(response => response.json())
.then(response => {
if (response.status === 429) {
throw new Error('Too many attempts. Please wait before trying again.');
}
return response.json();
})
.then(data => {
if (data.required) {
pinLength = data.length;
@@ -221,7 +226,16 @@
})
.catch(err => {
console.error('Error checking PIN requirement:', err);
document.getElementById('pin-error').textContent = 'Error checking PIN requirement';
const errorMessage = err.message === 'Too many attempts. Please wait before trying again.'
? err.message
: 'Error checking PIN requirement';
document.getElementById('pin-error').textContent = errorMessage;
// Prevent refresh loop by disabling the PIN input form
const pinContainer = document.getElementById('pin-container');
if (pinContainer) {
pinContainer.style.opacity = '0.5';
pinContainer.style.pointerEvents = 'none';
}
});
</script>
</body>

View File

@@ -52,12 +52,36 @@ app.get('/', (req, res) => {
// Login route
app.get('/login.html', (req, res) => {
// Add cache control headers
res.set('Cache-Control', 'no-store, no-cache, must-revalidate, private');
res.set('Pragma', 'no-cache');
res.set('Expires', '0');
let html = fs.readFileSync(path.join(__dirname, '../public', 'login.html'), 'utf8');
html = html.replace(/{{SITE_TITLE}}/g, config.siteTitle);
res.send(html);
});
// Serve static files
// Serve static files with template variable replacement for HTML files
app.use((req, res, next) => {
if (!req.path.endsWith('.html')) {
return next();
}
try {
const filePath = path.join(__dirname, '../public', req.path);
let html = fs.readFileSync(filePath, 'utf8');
html = html.replace(/{{SITE_TITLE}}/g, config.siteTitle);
if (req.path === 'index.html') {
html = html.replace('{{AUTO_UPLOAD}}', config.autoUpload.toString());
}
res.send(html);
} catch (err) {
next();
}
});
// Serve remaining static files
app.use(express.static('public'));
// Error handling middleware