Koa Basic HTTP Authentication Middleware
koa-basic-auth provides a straightforward middleware for implementing blanket HTTP Basic Authentication within Koa applications. It's designed for simple use cases where a single username and password (or just one of them since v4.0.0) protects all subsequent middleware in the stack. The current stable version is 4.0.0. Releases are tied to the Koa ecosystem, typically stable and less frequent, with major updates addressing underlying security practices or JavaScript module changes. Its key differentiator is its simplicity and explicit focus on 'blanket' authentication, contrasting with more complex authentication libraries that offer granular control, roles, or advanced strategies. It is not intended for fine-grained access control but rather for protecting entire sections of an application.
Common errors
-
Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported
cause This error occurs when attempting to use `require()` to import an ES Module, or more commonly, trying to `import` a CommonJS module like `koa-basic-auth` in an ES Module context without proper interop mechanisms.fixEnsure your project's module system is consistent. If `koa-basic-auth` is a CommonJS module (which it is), use `const auth = require('koa-basic-auth');`. If in an ESM-only context, you might need to use `const { createRequire } = require('module'); const require = createRequire(import.meta.url); const auth = require('koa-basic-auth');` -
HTTP/1.1 500 Internal Server Error (when authentication fails)
cause The basic authentication failed, but the Koa application did not have a custom error handling middleware in place to catch the `ctx.throw(401)` error emitted by `koa-basic-auth`.fixAdd a `try...catch` block around your middleware usage as demonstrated in the quickstart example. This block should explicitly check for `err.status === 401` and handle it by setting `ctx.status = 401` and `ctx.set('WWW-Authenticate', 'Basic')`. -
HTTP/1.1 401 Unauthorized (but no browser/client prompt)
cause While a custom 401 error handler is present, it's not correctly setting the `WWW-Authenticate` header, which is essential for a client (like a web browser) to understand that Basic Auth credentials are required and to prompt the user.fixInside your 401 error handler, make sure `ctx.set('WWW-Authenticate', 'Basic');` is explicitly called. This header is crucial for initiating the client-side authentication challenge.
Warnings
- breaking Starting with v4.0.0, koa-basic-auth no longer requires both a `name` (username) and a `pass` (password) to be provided in the options object. Either `name` or `pass` (or both) can now be used for authentication. This change aligns with updated behavior in the underlying `basic-auth` module.
- gotcha koa-basic-auth provides 'blanket' authentication, meaning it applies to all downstream middleware from where it's mounted. For selective protection of specific paths or routes, it must be explicitly combined with routing middleware (e.g., `koa-router`) or `koa-mount`.
- gotcha Failing to implement custom 401 error handling for the `Koa.prototype.context.throw(401)` call will result in a generic 500 'Internal Server Error' instead of a proper 401 'Unauthorized' response. This also means the `WWW-Authenticate` header won't be set, preventing browsers from prompting for credentials.
Install
-
npm install koa-basic-auth -
yarn add koa-basic-auth -
pnpm add koa-basic-auth
Imports
- auth
import auth from 'koa-basic-auth'; // Incorrect for CommonJS-only packages in pure ESM context import { auth } from 'koa-basic-auth'; // Incorrect, it's a default exportconst auth = require('koa-basic-auth');
Quickstart
const auth = require('koa-basic-auth');
const Koa = require('koa');
const app = new Koa();
// custom 401 handling to present a Basic Auth challenge to the client
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
if (err.status === 401) {
ctx.status = 401;
ctx.set('WWW-Authenticate', 'Basic');
ctx.body = 'Authentication Required';
} else {
throw err;
}
}
});
// Apply basic authentication to all downstream middleware
// Use environment variables for sensitive credentials in production
app.use(auth({ name: 'tj', pass: process.env.BASIC_AUTH_PASS ?? 'tobi' }));
// This middleware will only execute if authentication succeeds
app.use(async (ctx) => {
ctx.body = 'Welcome, authenticated user!';
});
const port = process.env.PORT || 3000;
app.listen(port, function () {
console.log(`Koa server listening on port ${port}`);
});
// To test with curl: curl -H "Authorization: basic dGo6dG9iaQ==" http://localhost:3000/