Checking a Password
Part of the Auth and Security section of Coddy's Node.js journey. Lesson 2 of 17.
A hash cannot be reversed, so a login never reads the stored password back. You hash the attempt the same way and compare the two keys. Same way means the same salt: split the stored salt:hash and reuse its salt.
Compare with timingSafeEqual, not ===. === stops at the first byte that differs, so an attacker who times many answers learns how much of a guess was right. timingSafeEqual always takes the same time. It compares two Buffers of the same length and throws when the lengths differ.
import { timingSafeEqual } from 'node:crypto';
const expected = Buffer.from(process.env.API_KEY);
const given = Buffer.from(req.get('x-api-key') ?? '');
const ok = given.length === expected.length && timingSafeEqual(given, expected);Buffer.from(hex, 'hex') turns hex text back into bytes.
Challenge
Easy- In
passwords.js, add and exportverifyPassword(password, stored): true when the password made that stored value. - In
server.js, addPOST /loginwith{ username, password }: 200{ username }, or 401{ "error": "Wrong username or password" }for a wrong password or an unknown name.
Sign up ada, log in, then log in with a wrong password.
Try it yourself
import { randomBytes, scrypt } from 'node:crypto';
import { promisify } from 'node:util';
const scryptAsync = promisify(scrypt);
// Turns a password into the text signup stores.
export async function hashPassword(password) {
const salt = randomBytes(16).toString('hex');
const key = await scryptAsync(password, salt, 64);
return `${salt}:${key.toString('hex')}`;
}
All lessons in Auth and Security
2Sessions and Cookies
Remembering with CookiesLogin Sessions