Password hashing library using Argon2id with factory pattern for dependency injection. This library provides secure password hashing without direct process.env access.
The @qauth-labs/server-password library provides:
- Argon2id password hashing - Industry-standard password hashing algorithm
- Factory pattern - Configuration-based instantiation (no
process.envaccess) - Type-safe API - Full TypeScript support
- Testable - Easy to inject mock configurations
This library is part of the QAuth monorepo and is automatically available to other projects within the workspace.
import { createPasswordHasher, DEFAULT_PASSWORD_CONFIG } from '@qauth-labs/server-password';import { createPasswordHasher } from '@qauth-labs/server-password';
// Create hasher with default configuration (config is optional)
const hasher = createPasswordHasher();
// Hash a password
const hashed = await hasher.hashPassword('mySecurePassword123');
// Verify a password
const isValid = await hasher.verifyPassword(hashed, 'mySecurePassword123');import { createPasswordHasher } from '@qauth-labs/server-password';
// Create hasher with custom configuration
const hasher = createPasswordHasher({
memoryCost: 32768, // 32MB (lower for faster hashing)
timeCost: 2, // 2 iterations
parallelism: 2, // 2 threads
});
const hashed = await hasher.hashPassword('password');import { createPasswordHasher } from '@qauth-labs/server-password';
import { env } from '@qauth-labs/server-config';
// Use validated environment variables
const hasher = createPasswordHasher({
memoryCost: env.PASSWORD_MEMORY_COST,
timeCost: env.PASSWORD_TIME_COST,
parallelism: env.PASSWORD_PARALLELISM,
});Creates a password hasher instance with the given configuration. Configuration is optional and partial - missing values will use defaults.
Parameters:
interface PasswordHashConfig {
memoryCost?: number; // Memory cost in KB (default: 65536 = 64MB)
timeCost?: number; // Time cost / iterations (default: 3)
parallelism?: number; // Parallelism / threads (default: 4)
}Returns: PasswordHasher instance
Throws: ZodError if the configuration is invalid
interface PasswordHasher {
/**
* Hash a password using Argon2id
* @param password - Plain text password to hash
* @returns Hashed password string
* @throws Error if hashing fails
*/
hashPassword(password: string): Promise<string>;
/**
* Verify a password against a hash
* @param hashedPassword - Previously hashed password string
* @param plainPassword - Plain text password to verify
* @returns True if password matches, false otherwise (including invalid hash format)
*/
verifyPassword(hashedPassword: string, plainPassword: string): Promise<boolean>;
}Default password hashing configuration:
{
memoryCost: 65536, // 64MB
timeCost: 3,
parallelism: 4,
}-
memoryCost: Memory cost in KB. Higher values increase security but require more memory.
- Default:
65536(64MB) - Minimum:
1KB - Recommended: At least
8192KB (8MB) for security
- Default:
-
timeCost: Number of iterations. Higher values increase security but take more time.
- Default:
3 - Minimum:
1 - Maximum:
10(higher values may cause performance issues)
- Default:
-
parallelism: Number of threads. Higher values can improve performance on multi-core systems.
- Default:
4 - Minimum:
1 - Maximum:
255(Argon2 specification limit)
- Default:
When using with @qauth-labs/server-config, these environment variables are validated:
PASSWORD_MEMORY_COST=65536 # Memory cost in KB
PASSWORD_TIME_COST=3 # Time cost / iterations
PASSWORD_PARALLELISM=4 # Parallelism / threadsimport { createPasswordHasher } from '@qauth-labs/server-password';
const hasher = createPasswordHasher(); // Uses defaults
async function registerUser(email: string, password: string) {
// Hash password before storing
const passwordHash = await hasher.hashPassword(password);
// Store user with hashed password
await createUser({ email, passwordHash });
}import { createPasswordHasher } from '@qauth-labs/server-password';
const hasher = createPasswordHasher(); // Uses defaults
async function loginUser(email: string, password: string) {
const user = await findUserByEmail(email);
if (!user) {
throw new Error('User not found');
}
// Verify password
const isValid = await hasher.verifyPassword(user.passwordHash, password);
if (!isValid) {
throw new Error('Invalid password');
}
// Remove passwordHash from response
const { passwordHash: _, ...safeUser } = user;
return safeUser;
}import { createPasswordHasher } from '@qauth-labs/server-password';
// Use lower-cost configuration for faster tests
const testHasher = createPasswordHasher({
memoryCost: 16384, // 16MB (faster for tests)
timeCost: 2, // 2 iterations
parallelism: 2, // 2 threads
});
describe('Password hashing', () => {
it('should hash and verify passwords', async () => {
const password = 'testPassword123';
const hashed = await testHasher.hashPassword(password);
const isValid = await testHasher.verifyPassword(hashed, password);
expect(isValid).toBe(true);
});
});- Never store plain text passwords - Always hash passwords before storing
- Never return password hashes in API responses - Always remove
passwordHashfrom user objects before sending to clients - Use appropriate configuration - Higher
memoryCostandtimeCostvalues provide better security but may impact performance - Handle errors - Password hashing can fail; always wrap in try-catch blocks
- Invalid hash handling -
verifyPasswordreturnsfalsefor invalid hash formats (does not throw)
If you're migrating from the old direct function calls:
Before:
import { hashPassword, verifyPassword } from '@qauth-labs/server-password';
const hashed = await hashPassword(password);
const isValid = await verifyPassword(hashed, password);After:
import { createPasswordHasher } from '@qauth-labs/server-password';
const hasher = createPasswordHasher(); // Config is optional
const hashed = await hasher.hashPassword(password);
const isValid = await hasher.verifyPassword(hashed, password);nx test passwordnx lint password@node-rs/argon2: Fast Argon2 implementation in Rust (Node.js bindings)zod: Schema validation for configuration
@qauth-labs/shared-validation: Password strength validation@qauth-labs/server-config: Environment configuration and validation@qauth-labs/fastify-plugin-password: Fastify plugin for password services
Apache-2.0