Fix Broken User Authentication in Sails
Broken Authentication in Sails.js often stems from weak credential storage, lack of rate limiting, and insecure session management. As an AppSec researcher, I see developers relying on plaintext comparisons or obsolete algorithms like MD5. To harden a Sails app, you must implement strong password hashing (Argon2 or Bcrypt), enforce secure session cookies, and prevent user enumeration.
The Vulnerable Pattern
// api/controllers/AuthController.js
module.exports = {
login: async function (req, res) {
const { email, password } = req.body;
const user = await User.findOne({ email });
// VULNERABILITY: Plaintext comparison and user enumeration risk
if (!user) return res.status(404).send('User not found');
if (user.password === password) {
req.session.userId = user.id;
return res.ok();
}
return res.status(401).send('Wrong password');
}
};
The Secure Implementation
The secure implementation fixes three critical flaws. First, it replaces plaintext comparison with Bcrypt, which is computationally expensive and resistant to brute-force. Second, it returns a generic error message regardless of whether the email or password was wrong, stopping attackers from mapping valid accounts. Third, it assumes the session configuration (config/session.js) is hardened with 'httpOnly' to block XSS-based cookie theft and 'secure' to ensure cookies only travel over HTTPS. Additionally, always implement a 'beforeCreate' hook in the User model to hash passwords before they ever touch the database.
// api/controllers/AuthController.js const bcrypt = require('bcrypt');module.exports = { login: async function (req, res) { const { email, password } = req.body; // 1. Use a generic error message to prevent enumeration const genericError = ‘Invalid email or password’;
try { const user = await User.findOne({ email }); if (!user) return res.forbidden(genericError); // 2. Use bcrypt.compare to mitigate timing attacks and handle hashes const isMatch = await bcrypt.compare(password, user.password); if (!isMatch) return res.forbidden(genericError); // 3. Regenerate session to prevent fixation req.session.userId = user.id; // Ensure config/session.js has: cookie: { secure: true, httpOnly: true, sameSite: 'strict' } return res.ok({ message: 'Authenticated' }); } catch (err) { return res.serverError(err); }
} };
Your Sails API
might be exposed to Broken User Authentication
74% of Sails apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
Free Tier • No Credit Card • Instant Report
Verified by Ghost Labs Security Team
This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.