mirror of
https://github.com/DumbWareio/DumbDrop.git
synced 2025-10-22 23:31:57 +00:00
feat: pin not working when rate limited redirect fix & allow non https baseUrl pin fix (#32)
* feat: ratelimit pin not working with baseUrl fix * Remove white space changes * Refactor PIN verification error handling and input state management - Improve error handling in login page JavaScript - Standardize API response structure with explicit success and error fields - Enhance user feedback for PIN authentication failures - Implement more robust input state management during login attempts * Fix PIN verification logic in root route - Improve PIN verification check to handle missing cookie scenario - Add explicit check for cookie existence before comparing PIN - Enhance root route authentication logic for more robust access control
This commit is contained in:
@@ -78,7 +78,6 @@
|
||||
const createPinInputs = (length) => {
|
||||
const form = document.getElementById('pin-form');
|
||||
form.innerHTML = ''; // Clear existing inputs
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'password';
|
||||
@@ -130,29 +129,32 @@
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ pin })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Simplified success and error handling
|
||||
if (data.success) {
|
||||
window.location.href = '/';
|
||||
} else {
|
||||
// Show error message
|
||||
document.getElementById('pin-error').textContent = data.error;
|
||||
document.getElementById('pin-error').textContent = data.error || 'Authentication failed';
|
||||
|
||||
// Only clear inputs and focus if not locked out
|
||||
if (!data.error.includes('try again in')) {
|
||||
const inputs = [...document.querySelectorAll('.pin-digit')];
|
||||
// Determine if it's a lockout scenario
|
||||
const isLockedOut = data.error.includes('Too many PIN verification attempts');
|
||||
|
||||
const inputs = [...document.querySelectorAll('.pin-digit')];
|
||||
if (isLockedOut) {
|
||||
// Disable inputs if locked out
|
||||
inputs.forEach(input => {
|
||||
input.disabled = true;
|
||||
input.classList.add('locked');
|
||||
});
|
||||
} else {
|
||||
// Reset inputs for other error types
|
||||
inputs.forEach(input => {
|
||||
input.value = '';
|
||||
input.classList.remove('filled');
|
||||
});
|
||||
inputs[0].focus();
|
||||
} else {
|
||||
// If locked out, disable all inputs
|
||||
const inputs = [...document.querySelectorAll('.pin-digit')];
|
||||
inputs.forEach(input => {
|
||||
input.disabled = true;
|
||||
input.classList.add('locked');
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -239,4 +241,4 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@@ -14,6 +14,7 @@ const { config, validateConfig } = require('./config');
|
||||
const logger = require('./utils/logger');
|
||||
const { ensureDirectoryExists } = require('./utils/fileUtils');
|
||||
const { securityHeaders, requirePin } = require('./middleware/security');
|
||||
const { safeCompare } = require('./utils/security');
|
||||
const { initUploadLimiter, pinVerifyLimiter, downloadLimiter } = require('./middleware/rateLimiter');
|
||||
|
||||
// Create Express app
|
||||
@@ -40,7 +41,8 @@ app.use('/api/files', requirePin(config.pin), downloadLimiter, fileRoutes);
|
||||
|
||||
// Root route
|
||||
app.get('/', (req, res) => {
|
||||
if (config.pin && !req.cookies.DUMBDROP_PIN) {
|
||||
// Check if the PIN is configured and the cookie exists
|
||||
if (config.pin && (!req.cookies?.DUMBDROP_PIN || !safeCompare(req.cookies.DUMBDROP_PIN, config.pin))) {
|
||||
return res.redirect('/login.html');
|
||||
}
|
||||
|
||||
|
@@ -24,11 +24,11 @@ router.post('/verify-pin', (req, res) => {
|
||||
if (!config.pin) {
|
||||
res.cookie('DUMBDROP_PIN', '', {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
secure: req.secure || (process.env.NODE_ENV === 'production' && config.baseUrl.startsWith('https')),
|
||||
sameSite: 'strict',
|
||||
path: '/'
|
||||
});
|
||||
return res.json({ success: true });
|
||||
return res.json({ success: true, error: null });
|
||||
}
|
||||
|
||||
// Validate PIN format
|
||||
@@ -36,6 +36,7 @@ router.post('/verify-pin', (req, res) => {
|
||||
if (!cleanedPin) {
|
||||
logger.warn(`Invalid PIN format from IP: ${ip}`);
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: 'Invalid PIN format. PIN must be 4-10 digits.'
|
||||
});
|
||||
}
|
||||
@@ -49,7 +50,8 @@ router.post('/verify-pin', (req, res) => {
|
||||
|
||||
logger.warn(`Login attempt from locked out IP: ${ip}`);
|
||||
return res.status(429).json({
|
||||
error: `Too many attempts. Please try again in ${timeLeft} minutes.`
|
||||
success: false,
|
||||
error: `Too many PIN verification attempts. Please try again in ${timeLeft} minutes.`
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,13 +63,13 @@ router.post('/verify-pin', (req, res) => {
|
||||
// Set secure cookie with cleaned PIN
|
||||
res.cookie('DUMBDROP_PIN', cleanedPin, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
secure: req.secure || (process.env.NODE_ENV === 'production' && config.baseUrl.startsWith('https')),
|
||||
sameSite: 'strict',
|
||||
path: '/'
|
||||
});
|
||||
|
||||
logger.info(`Successful PIN verification from IP: ${ip}`);
|
||||
res.json({ success: true });
|
||||
res.json({ success: true, error: null });
|
||||
} else {
|
||||
// Record failed attempt
|
||||
const attempts = recordAttempt(ip);
|
||||
@@ -78,12 +80,12 @@ router.post('/verify-pin', (req, res) => {
|
||||
success: false,
|
||||
error: attemptsLeft > 0 ?
|
||||
`Invalid PIN. ${attemptsLeft} attempts remaining.` :
|
||||
'Too many attempts. Account locked for 15 minutes.'
|
||||
'Too many PIN verification attempts. Account locked for 15 minutes.'
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(`PIN verification error: ${err.message}`);
|
||||
res.status(500).json({ error: 'Authentication failed' });
|
||||
res.status(500).json({ success: false, error: 'Authentication failed' });
|
||||
}
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user