Passken-express.js is an open source password management library for Express.js.
It includes @dwtechs/passken and adds Express middlewares to be used in a node.js service.
- 🪶 Very lightweight
- đź§Ş Thoroughly tested
- đźšš Shipped as EcmaScrypt Express module
- 📝 Written in Typescript
- node: 22
This is the oldest targeted versions.
$ npm i @dwtechs/passken-expressimport * as pk from "@dwtechs/passken-express";
import express from "express";
const router = express.Router();
import user from "../controllers/user.js";
import mail from "../controllers/mail.js";
import consumer from "../controllers/consumer.js";
const passwordOptions = {
len: 14,
num: true,
ucase: false,
lcase: false,
sym: false,
strict: true,
similarChars: true,
};
pk.init(passwordOptions);
// middleware sub-stacks
// add users
const addMany = [
user.validate,
pk.create,
user.addMany,
mail.sendRegistration,
];
// Login user
const login = [
user.validate,
user.getPwd,
pk.compare,
user.isActive,
];
// Routes
// log a user with his email & password
router.post("/", login);
// Add new users
router.post("/", addMany);You do not need to initialise the library using pwd.init() if the default config is fine for you.
Passken will start with the following default password configuration :
Options = {
len: 12,
num: true,
ucase: true,
lcase: true,
sym: false,
strict: true,
similarChars: false,
};You do not need to intialise the library using pwd.init() if you are using the following environment variables:
PWD_RAND_LENGTH,
PWD_RAND_NUMBERS,
PWD_RAND_UPPERCASE,
PWD_RAND_LOWERCASE,
PWD_RAND_SYMBOLS,
PWD_RAND_STRICT,
PWD_RAND_SIMILAR_CHARS,
PWD_SECRET,These environment variables will update the default values of the lib at start up. So you do not need to init the library in the code.
Note that PWD_SECRET is mandatory.
type Options = {
len: number,
num: boolean,
ucase: boolean,
lcase: boolean,
sym: boolean,
strict: boolean,
similarChars: boolean,
};/**
* Initializes the password generation options for the Passken-express library.
*
* This function sets the global password options that will be used by the `create` function
* when generating random passwords. The options control password characteristics such as
* length, character sets, and complexity requirements.
*
* @param {Options} options - Password generation options from @dwtechs/passken
* @param {number} options.len - Password length (minimum characters)
* @param {boolean} options.num - Include numbers in password
* @param {boolean} options.ucase - Include uppercase letters
* @param {boolean} options.lcase - Include lowercase letters
* @param {boolean} options.sym - Include symbols in password
* @param {boolean} options.strict - Password must include at least one character from each enabled pool
* @param {boolean} options.similarChars - Allow visually similar characters (l, I, 1, o, O, 0)
*
* @returns {void}
*
* **Input Properties:**
* - `options` (Options object) - Password generation configuration
*
* **Output Properties:**
* - None (sets global configuration)
*
* @example
* ```typescript
* import { init } from '@dwtechs/passken-express';
*
* // Initialize with custom password options
* init({
* len: 16,
* num: true,
* ucase: true,
* lcase: true,
* sym: true,
* strict: true,
* similarChars: false
* });
* ```
*/
function init(options: Options): void {}
/**
* Express middleware to compare a user-provided password with a stored hashed password.
*
* This middleware validates that a plaintext password from the request matches a hashed
* password from the database. It extracts the password from the request body and the
* hash from either the response rows or response object, then uses Passken's secure
* comparison function to verify the match.
*
* @param {Request} req - Express request object containing the password
* @param {MyResponse} res - Express response object containing the database hash
* @param {NextFunction} next - Express next function to continue middleware chain
*
* @returns {void} Calls next() to continue, or next(error) on failure
*
* @throws {InvalidPasswordError} If the password is invalid or does not match the hash (HTTP 400)
* @throws {InvalidBase64SecretError} If the secret is not a valid base64 string (HTTP 400)
* @throws {Object} Will call next() with error object containing:
* - statusCode: 400 - When password is missing from request body
* - statusCode: 400 - When hash is missing from response data
* - statusCode: 401 - When password doesn't match the stored hash
*
* @example
* ```typescript
* import { compare } from '@dwtechs/passken-express';
*
* // Usage in Express route after database query
* app.post('/login', getUserFromDB, compare, (req, res) => {
* res.json({ message: 'Login successful' });
* });
*
* // Request body should contain:
* // { "password": "user-password" } or { "pwd": "user-password" }
*
* // Response should contain hash from database:
* // res.rows[0].password or res.rows[0].pwd or res.password or res.pwd
* ```
*/
function compare(req: Request, res: MyResponse, next: NextFunction): void {}
/**
* Express middleware to generate random passwords and encrypt them for multiple users.
*
* This middleware generates secure random passwords for multiple user records and encrypts
* them using Passken's encryption function. It processes an array of user objects in the
* request body, adding both plaintext and encrypted password fields to each record.
* The plaintext passwords can be sent to users (e.g., via email) while encrypted passwords
* are stored in the database.
*
* @param {Request} req - Express request object containing user records in body.rows
* @param {Response} _res - Express response object (not used in this function)
* @param {NextFunction} next - Express next function to continue middleware chain
*
* @returns {void} Calls next() to continue, or next(error) on failure
*
* @throws {InvalidPasswordError} If password generation or encryption fails (HTTP 400)
* @throws {InvalidBase64SecretError} If the secret is not a valid base64 string (HTTP 400)
* @throws {Object} Will call next() with error object containing:
* - statusCode: 400 - When req.body.rows is missing or not an array
*
* @example
* ```typescript
* import { create } from '@dwtechs/passken-express';
*
* // Usage in Express route for bulk user creation
* app.post('/users/bulk', create, saveUsersToDatabase, (req, res) => {
* // Send plaintext passwords to users via email
* req.body.rows.forEach(user => {
* sendPasswordEmail(user.email, user.pwd);
* });
* res.json({ message: 'Users created successfully' });
* });
*
* // Request body should contain:
* // { "rows": [{ "name": "User1", "email": "user1@example.com" }, ...] }
*
* // After processing, each row will have:
* // { "name": "User1", "email": "user1@example.com", "pwd": "generated-password", "encryptedPwd": "encrypted-hash" }
* ```
*/
function create(req: Request, res: Response, next: NextFunction): void {}The function will look for a password value from the client request body :
const pwd = req.body?.password || req.body?.pwd || req.body?.pwdHash.It will then look for the hashed password stored in the database :
const hash = res.password
|| res.pwd
|| res.pwdHash
|| res.rows[0].password
|| res.rows[0].pwd
|| res.rows[0].pwdHash
|| res.locals.rows[0].password
|| res.locals.rows[0].pwd
|| res.locals.rows[0].pwdHash;The function will loop through an array in req.body.rows.
It will throw an error if req.body.rows is missing or empty.
New passwords will be added into req.body.rows[i].pwd. Encrypted passwords will be added into req.body.rows[i].encryptedPwd .
Any of these can be passed into the options object for each function.
| Name | type | Description | Default |
|---|---|---|---|
| len | Integer | Minimal length of password. | 12 |
| num* | Boolean | use numbers in password. | true |
| sym* | Boolean | use symbols in password | true |
| lcase* | Boolean | use lowercase in password | true |
| ucase* | Boolean | use uppercase letters in password. | true |
| strict | Boolean | password must include at least one character from each pool. | true |
| similarChars | Boolean | allow close looking chars. | false |
*At least one of those options must be true.
Symbols used : !@#%*_-+=:;?><,./() Similar characters : l, I, 1, o, O, 0
Passken-express.js uses @dwtechs/Winstan library for logging. All logs are in debug mode. Meaning they should not appear in production mode.
Passken-express.js is still in development and we would be glad to get all the help you can provide. To contribute please read contributor.md for detailed installation guide.
| Purpose | Choice | Motivation |
|---|---|---|
| repository | Github | hosting for software development version control using Git |
| package manager | npm | default node.js package manager |
| language | TypeScript | static type checking along with the latest ECMAScript features |
| module bundler | Rollup | advanced module bundler for ES6 modules |
| unit testing | Jest | delightful testing with a focus on simplicity |