Password and email validation library with factory pattern for dependency injection. This library provides password strength validation and email format validation without direct process.env access.
The @qauth-labs/shared-validation library provides:
- Password strength validation - Using zxcvbn algorithm with configurable minimum score
- Email validation - Format validation and normalization
- Factory pattern - Configuration-based instantiation (no
process.envaccess for password validation) - 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 {
createPasswordValidator,
DEFAULT_PASSWORD_VALIDATION_CONFIG,
validateEmail,
} from '@qauth-labs/shared-validation';import {
createPasswordValidator,
DEFAULT_PASSWORD_VALIDATION_CONFIG,
} from '@qauth-labs/shared-validation';
// Create validator with default configuration
const validator = createPasswordValidator(DEFAULT_PASSWORD_VALIDATION_CONFIG);
// Validate password strength
const result = validator.validatePasswordStrength('mySecurePassword123');
if (!result.valid) {
console.log('Password is too weak:', result.feedback);
console.log('Score:', result.score); // 0-4
}import { createPasswordValidator } from '@qauth-labs/shared-validation';
// Create validator with custom minimum score
const strictValidator = createPasswordValidator({ minScore: 3 }); // Good minimum
const lenientValidator = createPasswordValidator({ minScore: 1 }); // Weak minimum
const result = strictValidator.validatePasswordStrength('password');Email validation doesn't require configuration, so it's available as a direct function:
import { validateEmail, normalizeEmail, isValidEmail } from '@qauth-labs/shared-validation';
// Validate and normalize email (throws if invalid)
try {
const normalized = validateEmail('User@Example.com');
// Returns: 'user@example.com'
} catch (error) {
// Handle validation error
}
// Normalize email (no validation)
const normalized = normalizeEmail('User@Example.com');
// Returns: 'user@example.com'
// Check if email is valid (non-throwing)
if (isValidEmail('user@example.com')) {
// Email is valid
}import { createPasswordValidator } from '@qauth-labs/shared-validation';
import { env } from '@qauth-labs/server-config';
// Use validated environment variables
const validator = createPasswordValidator({
minScore: env.PASSWORD_MIN_SCORE,
});Creates a password validator instance with the given configuration. Configuration is optional and partial - missing values will use defaults.
Parameters:
interface PasswordValidationConfig {
minScore?: number; // Minimum password strength score (0-4, default: 2)
}Returns: PasswordValidator instance
Throws: ZodError if the configuration is invalid
interface PasswordValidator {
/**
* Validate password strength using zxcvbn
* @param password - Password to validate
* @returns Password strength validation result
*/
validatePasswordStrength(password: string): PasswordStrengthResult;
}interface PasswordStrengthResult {
valid: boolean; // Whether password meets minimum strength
score: number; // Password strength score (0-4)
feedback?: string[]; // Feedback messages from zxcvbn
crackTimeSeconds?: number; // Estimated time to crack (seconds)
}- 0: Very weak
- 1: Weak
- 2: Fair (default minimum)
- 3: Good
- 4: Strong
Validates email format and returns normalized email. Throws ZodError if invalid.
Parameters:
email: Email address to validate
Returns: Normalized email address (lowercase, trimmed)
Throws: ZodError if email format is invalid
Normalizes email address (lowercase, trimmed) without validation.
Parameters:
email: Email address to normalize
Returns: Normalized email address
Checks if email format is valid without throwing.
Parameters:
email: Email address to check
Returns: true if email format is valid, false otherwise
Default password validation configuration:
{
minScore: 2, // Fair strength minimum
}- minScore: Minimum password strength score (0-4)
- Default:
2(Fair) 0: Very weak (not recommended)1: Weak (not recommended)2: Fair (recommended default)3: Good (recommended for sensitive applications)4: Strong (very strict)
- Default:
When using with @qauth-labs/server-config, this environment variable is validated:
PASSWORD_MIN_SCORE=2 # Minimum password strength score (0-4)import { createPasswordValidator, validateEmail } from '@qauth-labs/shared-validation';
const validator = createPasswordValidator(); // Uses defaults
async function registerUser(email: string, password: string) {
// Validate and normalize email
const normalizedEmail = validateEmail(email);
// Validate password strength
const strength = validator.validatePasswordStrength(password);
if (!strength.valid) {
throw new Error('Password is too weak: ' + strength.feedback?.join(', '));
}
// Create user with validated data
await createUser({ email: normalizedEmail, password });
}import { validateEmail, normalizeEmail } from '@qauth-labs/shared-validation';
async function loginUser(email: string, password: string) {
// Normalize email for lookup (no validation needed for login)
const normalizedEmail = normalizeEmail(email);
// Find user by normalized email
const user = await findUserByEmail(normalizedEmail);
// ... rest of login logic
}import { createPasswordValidator } from '@qauth-labs/shared-validation';
// Use lenient configuration for tests
const testValidator = createPasswordValidator({ minScore: 1 });
describe('Password validation', () => {
it('should accept passwords meeting minimum score', () => {
const result = testValidator.validatePasswordStrength('password123');
expect(result.valid).toBe(true);
});
});If you're migrating from the old direct function calls:
Before:
import { validatePasswordStrength, validateEmail } from '@qauth-labs/shared-validation';
const strength = validatePasswordStrength(password);
const email = validateEmail(email);After:
import { createPasswordValidator, validateEmail } from '@qauth-labs/shared-validation';
const validator = createPasswordValidator(); // Config is optional
const strength = validator.validatePasswordStrength(password);
const email = validateEmail(email); // Still direct function (no config needed)- Password Strength: Use appropriate
minScorevalues based on your security requirements - Email Normalization: Always normalize emails before storing to prevent duplicate accounts
- Feedback Messages: Provide user-friendly feedback from validation results
- Empty Passwords: Empty passwords are automatically rejected (score 0)
nx test validationnx lint validationzxcvbn: Password strength estimationzod: Email format validation
@qauth-labs/server-password: Password hashing library@qauth-labs/server-config: Environment configuration and validation@qauth-labs/fastify-plugin-password: Fastify plugin for password services
Apache-2.0