Password Hashing, Token Storage, and Secure Practices
bcrypt, password hashing, salt rounds, token storage, httpOnly cookies, HTTPS, secret management, OWASP API security
Password Hashing, Token Storage, and Secure Practices
Authentication security is only as strong as its weakest implementation detail. Correct algorithm choices, storage patterns, and transmission security are what separate a secure REST API from a vulnerable one.
Password Hashing with bcrypt
Never store plaintext passwords. Always hash passwords using bcrypt, which is specifically designed for passwords โ it is slow by design (making brute-force attacks expensive) and includes a built-in salt to prevent rainbow table attacks.
const bcrypt = require('bcryptjs');
userSchema.pre('save', async function(next) {
if (!this.isModified('password')) return next();
this.password = await bcrypt.hash(this.password, 12);
next();
});
userSchema.methods.comparePassword = async function(candidatePassword) {
return bcrypt.compare(candidatePassword, this.password);
};Use a salt factor of 10-12 for production. Higher values increase security but also increase CPU time per login. 12 is a reasonable balance for most applications.
Where to Store JWT Tokens
Storing JWTs in localStorage is vulnerable to XSS attacks โ any JavaScript running on the page can read localStorage. Storing them in httpOnly cookies makes them inaccessible to JavaScript, mitigating XSS. Use the Secure flag to ensure cookies are only sent over HTTPS.
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000
});HTTPS Is Non-Negotiable
All REST API traffic in production must use HTTPS. HTTP transmits tokens and credentials in plaintext, making them trivially interceptable on any network. Use TLS certificates from Let's Encrypt (free) and enforce HTTPS redirection at the infrastructure level.
Secret Management
JWT secrets and database passwords must be randomly generated, stored in environment variables, rotated periodically, and managed with a secrets manager in production. A secret exposed in a Git commit must be rotated immediately, even if the commit was immediately deleted.
