htpasswd
The `htpasswd` package provides a Node.js implementation of Apache's `htpasswd` utility, designed for managing HTTP Basic Authentication password files. It functions primarily as a command-line interface tool, offering various password encryption methods including MD5 (default), bcrypt, SHA, crypt(), and plaintext. The current stable version is 2.4.6. Its release cadence appears to be infrequent, with recent updates mainly addressing ownership and minor version bumps rather than continuous feature additions. Key differentiators include its direct emulation of the Apache utility's CLI and support for multiple hashing algorithms, making it suitable for environments where direct `htpasswd` file manipulation is required programmatically or via script.
Common errors
-
htpasswd: command not found
cause The `htpasswd` CLI tool has not been installed globally or is not in your system's PATH.fixInstall the package globally using `npm install -g htpasswd`. -
Error: file already exists
cause Attempting to create a new htpasswd file using the `-c` option when a file with the same name already exists.fixTo overwrite an existing file (which will delete all existing users), you must manually remove the old file first or confirm the overwrite via CLI prompt (if available) or programmatic option. If you intend to add a user to an existing file, omit the `-c` flag. -
Password mismatch during verification, even though the password seems correct.
cause This often happens if the password was originally hashed with an insecure or deprecated algorithm (e.g., MD5, SHA, crypt) or a different bcrypt cost than what is currently being used for verification attempts, or if the password was truncated by an old algorithm.fixEnsure that the verification process uses the correct algorithm that matches how the password was originally stored. If using deprecated algorithms, consider migrating users to bcrypt. Check the actual hash in the `.htpasswd` file to confirm the algorithm used (e.g., `$2y$`, `$apr1$`, `$sha1$` prefixes indicate bcrypt, MD5, SHA respectively).
Warnings
- gotcha Using the `-b` option to pass passwords directly on the command line is insecure, as the password becomes visible in shell history and process lists (e.g., `ps aux`).
- gotcha The `-d` (crypt), `-s` (SHA), and `-p` (plaintext) encryption algorithms are considered insecure by modern standards. Using them can compromise the security of your authentication.
- gotcha When using bcrypt with the `-C` option (cost), note that the default cost of 5 might be too low for high-security applications. Higher costs increase computational time, making brute-force attacks more difficult.
Install
-
npm install htpasswd -
yarn add htpasswd -
pnpm add htpasswd
Imports
- Htpasswd
import Htpasswd from 'htpasswd';
import { Htpasswd } from 'htpasswd'; - createHash
const createHash = require('htpasswd').createHash;import { createHash } from 'htpasswd'; - CommonJS named exports
const { Htpasswd, createHash, verifyPassword } = require('htpasswd');
Quickstart
import { Htpasswd } from 'htpasswd';
import * as path from 'path';
import * as fs from 'fs/promises';
async function runHtpasswdExample() {
const filePath = path.join(__dirname, 'example.htpasswd');
const username = 'testuser';
const password = 'securePassword123';
const wrongPassword = 'wrongPassword';
try {
// 1. Create a new htpasswd file and add a user (using bcrypt by default)
// Default bcrypt cost is 5. Using 10 here for better security.
const htpasswd = new Htpasswd(filePath, { create: true, bcrypt: true, cost: 10 });
await htpasswd.add(username, password);
console.log(`User '${username}' added to '${filePath}' with bcrypt hash.`);
const content = await fs.readFile(filePath, 'utf8');
console.log('File content:\n', content);
// 2. Verify the correct password
const isCorrect = await htpasswd.verify(username, password);
console.log(`Password for '${username}' is correct: ${isCorrect}`);
// 3. Try to verify with a wrong password
const isWrong = await htpasswd.verify(username, wrongPassword);
console.log(`Password for '${username}' with wrong input: ${isWrong}`);
// 4. Delete the user
await htpasswd.delete(username);
console.log(`User '${username}' deleted from '${filePath}'.`);
const updatedContent = await fs.readFile(filePath, 'utf8');
console.log('File content after deletion:\n', updatedContent);
} catch (error: any) {
console.error('Error during htpasswd operations:', error.message);
} finally {
// Clean up the created file
try {
await fs.unlink(filePath);
console.log(`Cleaned up '${filePath}'.`);
} catch (e) {
// Ignore if file doesn't exist or permissions issue during cleanup
}
}
}
runHtpasswdExample();