Connect Basic Authentication Middleware
`basic-auth-connect` is a Connect/Express middleware that implements HTTP Basic Authentication, providing a straightforward way to secure web routes. It allows for user verification using either static username/password pairs or through synchronous or asynchronous callback functions for more dynamic authentication logic. The package is currently on version 1.1.0, with its most recent updates focusing primarily on security patches, notably addressing CVE-2024-47178. While functional and easy to use for common Basic Auth scenarios, the package's own documentation suggests that for more complex or highly custom authentication requirements, developers should consider using the underlying `basic-auth` package directly to build their own middleware. Its release cadence appears to be driven by critical security fixes rather than feature development, indicating it is in a maintenance status. Its key differentiator is its simplicity for direct integration into the Connect middleware stack.
Common errors
-
ReferenceError: require is not defined
cause Attempting to use `require('basic-auth-connect')` in an ES module (ESM) context in Node.js without proper setup.fixEnsure your project is configured for CommonJS, or use a tool like `createRequire` from the `module` package if you must import CommonJS modules within an ESM file (`import { createRequire } from 'module'; const require = createRequire(import.meta.url); const basicAuth = require('basic-auth-connect');`). -
TypeError: basicAuth_1.default is not a function
cause Attempting to use `import basicAuth from 'basic-auth-connect';` which incorrectly assumes a default ES module export for a CommonJS module.fixUse the CommonJS `require()` syntax: `const basicAuth = require('basic-auth-connect');`. This package does not provide ES module exports.
Warnings
- breaking Version 1.1.0 fixed CVE-2024-47178, a timing attack vulnerability. All previous versions are affected. Update immediately to ensure secure password comparison.
- gotcha When using callback verification for authentication, it is critical to employ a time-safe comparison function (e.g., `crypto.timingSafeEqual`) for passwords to prevent timing attacks. Direct string comparison (`==` or `===`) is insecure.
- gotcha The README suggests considering direct usage of the `basic-auth` package for custom middleware. This implies `basic-auth-connect` might be less actively developed for new features and more maintained for security, making `basic-auth` a better choice for highly customized or long-term solutions.
Install
-
npm install basic-auth-connect -
yarn add basic-auth-connect -
pnpm add basic-auth-connect
Imports
- basicAuth
import basicAuth from 'basic-auth-connect';
const basicAuth = require('basic-auth-connect'); - basicAuth (named import)
import { basicAuth } from 'basic-auth-connect';const basicAuth = require('basic-auth-connect');
Quickstart
const connect = require('connect');
const basicAuth = require('basic-auth-connect');
const http = require('http');
const crypto = require('crypto');
const app = connect();
// Simulate a database user check with timing-safe comparison
const users = {
'tj': 'wahoo',
'admin': 'secret'
};
function verifyUser(user, pass, done) {
setTimeout(() => {
const storedPass = users[user];
if (storedPass) {
// Crucial for security: timing-safe comparison
const userBuffer = Buffer.from(pass);
const storedBuffer = Buffer.from(storedPass);
if (userBuffer.length === storedBuffer.length && crypto.timingSafeEqual(userBuffer, storedBuffer)) {
console.log(`User '${user}' authenticated successfully.`);
return done(null, user);
}
}
console.log(`Failed authentication for user '${user}'.`);
done(null, false); // Failed authentication
}, 100);
}
// Basic auth with static username/password
app.use('/protected-static', basicAuth('staticuser', 'staticpass'));
// Basic auth with async callback verification
app.use('/protected-async', basicAuth(verifyUser));
app.use('/protected-static', (req, res) => {
res.end('Accessed protected static route!');
});
app.use('/protected-async', (req, res) => {
res.end('Accessed protected async route!');
});
app.use('/', (req, res) => {
res.end('Welcome! Try /protected-static or /protected-async');
});
http.createServer(app).listen(3000, () => {
console.log('Server running on http://localhost:3000');
console.log('Try accessing http://localhost:3000/protected-static with staticuser/staticpass');
console.log('Try accessing http://localhost:3000/protected-async with tj/wahoo');
});