@thekid000/auth-basic-improve
v1.0.1
Published
node.js basic auth parser
Maintainers
Readme
@thekid000/auth-basic-improve
A lightweight, TypeScript-native Basic Authentication parser for Node.js & Express.js.
Supports static user validation, custom synchronouss/async authorizers, timing-safe comparisons, and configurable challenge headers.
Table of Contents
Features
- Core Parser: Extract
usernameandpasswordfrom base64-encoded Basic Auth headers. - Express Middleware: Drop-in authentication middleware for Express.js routes.
- Timing-Safe Comparison: Prevents timing attacks via
timingSafeEqual. - Flexible Authorizers: Use static user lists, sync, or async custom functions.
- Challenge Mode: Send
WWW-Authenticateheaders for browser pop-ups. - Custom Responses: Return static strings, JSON, or dynamic messages on 401.
- Fully Typed: 100% TypeScript with exported interfaces.
Installation
# Using Yarn (recommended, packageManager: [email protected])
yarn add @thekid000/auth-basic-improve
# Using npm
npm install @thekid000/auth-basic-improveRequirements: Node.js >= 24
Usage
1. Parse Basic Auth String
Extract credentials directly from a base64-encoded string:
import { parse } from "@thekid000/auth-basic-improve";
const result = parse("Basic Zm9vOmJhcg==");
// Returns: { name: "foo", pass: "bar" }
// Returns undefined for invalid/malformed header strings
// Throws TypeError if the input is not a string2. Extract Auth from Express Request
Parse the Authorization header from an Express Request object:
import { auth } from "@thekid000/auth-basic-improve";
app.get("/protected", (req, res) => {
const credentials = auth(req);
if (!credentials) {
return res.status(401).send("Unauthorized");
}
console.log(credentials.name); // "foo"
console.log(credentials.pass); // "bar"
res.send("Authenticated!");
});3. Express Middleware
Build a full authentication middleware with the named buildMiddleware export:
import { buildMiddleware } from "@thekid000/auth-basic-improve";Static Users
Define users directly in the options:
const authMiddleware = buildMiddleware({
challenge: false,
users: { Admin: "secret1234", User: "password123" },
});
app.get("/admin", authMiddleware, (req, res) => {
res.send("Welcome, Admin!");
});Custom Synchronous Authorizer
Provide your own validation logic:
const myAuthorizer = (username: string, password: string): boolean => {
// e.g., query a database
return username.startsWith("A") && password.startsWith("secret");
};
const authMiddleware = buildMiddleware({ authorizer: myAuthorizer });Custom Asynchronous Authorizer
For database lookups or async operations:
const myAsyncAuthorizer = (
username: string,
password: string,
cb: (err: Error | null, result: boolean) => void
): void => {
// Simulate async DB query
db.findUser(username, (err, user) => {
if (err) return cb(err, false);
cb(null, user && user.password === password);
});
};
const authMiddleware = buildMiddleware({
authorizeAsync: true,
authorizer: myAsyncAuthorizer,
});Challenge Mode
Send a WWW-Authenticate header to trigger browser credential prompts:
const authMiddleware = buildMiddleware({
challenge: true,
users: { Admin: "secret1234" },
});
// On 401, response includes: WWW-Authenticate: Basic realm="..."Custom realm:
const authMiddleware = buildMiddleware({
challenge: true,
realm: "My Protected Area",
users: { Admin: "secret1234" },
});
// Response: WWW-Authenticate: Basic realm="My Protected Area"Custom Response Body
Control the 401 response content:
// Static string
const authMiddleware = buildMiddleware({
unauthorizedResponse: "Access Denied",
});
// JSON object
const authMiddleware = buildMiddleware({
unauthorizedResponse: { error: "Unauthorized", code: 401 },
});
// Dynamic function
const authMiddleware = buildMiddleware({
unauthorizedResponse: (req) =>
req.auth
? `Credentials ${req.auth.user}:${req.auth.password} rejected`
: "No credentials provided",
users: { Foo: "bar" },
});Safe Compare
Use timing-safe byte comparison to reduce content-dependent timing differences:
import { safeCompare } from "@thekid000/auth-basic-improve";
const myAuthorizer = (username: string, password: string): boolean => {
return (
safeCompare(username, "ExpectedUser") &&
safeCompare(password, "ExpectedPass")
);
};API Reference
parse(str: string) => Credentials | undefined
Parses a base64-encoded Basic Authentication string into { name, pass }.
| Parameter | Type | Required | Description |
| --------- | -------- | -------- | --------------------- |
| str | string | Yes | Base64-encoded auth string |
Returns: { name: string, pass: string } on success, undefined for malformed or non-Basic header strings.
Throws: TypeError if str is not a string.
auth(req: Request) => Credentials | undefined
Extracts and parses the Authorization header from an Express request.
| Parameter | Type | Required | Description |
| --------- | --------- | -------- | ---------------------- |
| req | Request | Yes | Express request object |
Returns: { name: string, pass: string } on success, undefined on failure.
buildMiddleware(options: IbuildMiddleware) => (req, res, next) => void
Creates an Express authentication middleware.
| Option | Type | Default | Description |
| --------------------- | ------------------ | ---------------- | ------------------------------------ |
| challenge | boolean | false | Send WWW-Authenticate header |
| users | Record<string, string> | {} | Static username → password map |
| authorizer | function | — | Custom validation function |
| authorizeAsync | boolean | false | Enable async authorizer |
| unauthorizedResponse| unknown | "" | Custom 401 response body |
| realm | string \| function | undefined | Custom realm string or generator |
safeCompare(userInput: string, secret: string) => boolean
Compares strings using crypto.timingSafeEqual, avoiding an early exit when bytes differ. Runtime still depends on the longer input's byte length, so it is not constant-time across different input lengths.
Project Structure
src/
├── index.ts # Main entry point — re-exports everything
├── app.ts # Aggregates core auth module
├── basicAuth/
│ ├── index.ts # Core parser: parse() & auth()
│ └── base64.ts # Base64 encode/decode utilities
├── expressBasicAuth/
│ └── index.ts # Express middleware builder
└── interfaces/
├── basicAuth.interface.ts # Credentials, IRequestHeaderAuthorization
└── expressBasicAuth.interface.ts # IBasicAuthedRequest, IbuildMiddleware
tests/
├── unit/
│ ├── basicAuth.test.ts # Unit tests for parse() & auth()
│ ├── base64.spec.ts # Unit tests for base64 encode/decode
│ ├── format.spec.ts # Unit tests for format() (header formatting)
│ └── safeCompare.spec.ts # Unit tests for safeCompare()
├── integration/
│ └── expressBasicAuth.test.ts # Integration tests for middleware
└── benchmarks/
├── base64.bench.ts # Benchmarks for base64 decoding strategies
├── format.bench.ts # Benchmarks for format() performance
└── parse.bench.ts # Benchmarks for parse() performanceSee README_STRUCTURE.md for a detailed file-by-file breakdown.
Development
# Install dependencies
yarn install
# Build TypeScript → JavaScript
yarn build
# Run tests
yarn test
# Run tests with coverage
yarn test:coverage
# Run unit tests only
yarn test:unit
# Lint & fix
yarn lint
# Bundle size check
yarn sizeLicense
MIT © Tri Bui Quang
