Files
Anders Böttcher 0d58fafe4e feat: implement user authentication and admin management
- Add user management API endpoints for listing and creating users.
- Implement login and logout functionality with rate limiting.
- Create UI components for login form, logout button, and animated elements.
- Add session management with JWT and secure cookie handling.
- Seed initial admin user if no users exist.
- Introduce utility functions for password hashing and user authentication.
- Set up proxy middleware for route protection and security headers.
- Create a JSON file for user data storage.
- Add links configuration for external resources.
2026-05-12 14:58:11 +02:00

37 lines
1.1 KiB
TypeScript

import crypto from 'crypto'
// scrypt params: N=16384 gives ~100ms on modern hardware — deliberate slowdown
const SCRYPT_N = 16384
const SCRYPT_R = 8
const SCRYPT_P = 1
const KEY_LEN = 64
/** Hashes a password using scrypt. Returns the hex hash and a random hex salt. */
export async function hashPassword(password: string): Promise<{ hash: string; salt: string }> {
const salt = crypto.randomBytes(16).toString('hex')
const hash = await deriveKey(password, salt)
return { hash, salt }
}
/** Constant-time comparison to prevent timing attacks. */
export async function verifyPassword(
password: string,
hash: string,
salt: string,
): Promise<boolean> {
const derived = await deriveKey(password, salt)
const a = Buffer.from(derived, 'hex')
const b = Buffer.from(hash, 'hex')
if (a.length !== b.length) return false
return crypto.timingSafeEqual(a, b)
}
function deriveKey(password: string, salt: string): Promise<string> {
return new Promise((resolve, reject) => {
crypto.scrypt(password, salt, KEY_LEN, { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P }, (err, key) => {
if (err) reject(err)
else resolve(key.toString('hex'))
})
})
}