Basic HTTP auth in Express and Node.js
Hi, my name is Tina! I am a Full Stack Software Developer and Tech Lead from Canada. 🙋🏻♀️
Search for a command to run...
Hi, my name is Tina! I am a Full Stack Software Developer and Tech Lead from Canada. 🙋🏻♀️
No comments yet. Be the first to comment.
Have you ever installed a package by using go install <some-package> and wondered how to uninstall it? Go is really great in that respect. Go packages are a single binary and they’re installed based on how your Go tooling is set up. Provided we have ...

Overview This is the 3rd article in a series of posts about working with Open API to create generated API clients and documentation websites. In the 1st post we went over what we can do with Open API spec files, e.g. generate API clients and documen...

Overview This article is the 2nd in a series of blog posts that discuss using Open API to help with API documentation and API client code generation. In the previous article, we went over how we can generate documentation and API clients using existi...

Overview This article starts a series of Open API-related blog posts. OpenAPI, previously known as Swagger (a name still in use today for many of its tools), is a suite of tools that generate documentation and networking clients for various programmi...

You've probably already seen the scary alert (that's possibly why you're here), but in case you haven't, it looks something like this: NewAppIJustDownloaded pasted from your clipboard Sometimes it h

When you're looking for a quick and dirty way to add password protection to a website, basic HTTP auth is handy. This tutorial will go through implementing basic HTTP auth for a static website using Express.js in Node.js.
Basic HTTP auth is simple username and password login protection for a website. It is not recommended to use this in a real, production-level project as it is not very elegant, but it works for the simple task of password protecting a website.

I implemented basic HTTP auth in this resumé website project.
This is some basic code for setting up an Express app.
// ./server/index.js
const express = require('express');
const Path = require('path');
const app = express();
const port = process.env.PORT || 8000;
/**
* Routes
*/
app.use('/', express.static(Path.join(__dirname, '../static')));
app.listen(port, () => { console.log(`Listening on port ${port}`); });
Essentially what this code does is create an Express server that listens on port 8000 and serves a directory located in the project root in ./static. This will be the site we password protect.
To add basic HTTP auth in Express, we are going to leverage a handy plugin that the Express team recommends. It's called basic-auth. There are similar packages out there (including ones with the name express) but this is the one that works and that the Express team recommends. We will also be using the tsscmp library, which stands for timing-safe string comparison. This will allow us to perform time-safe equality checks on our strings. Further reading on implementing time-safe string comparisons can be found in the blog post or by reading this library's source code.
Now let's add these to our project with Yarn:
yarn add tsscmp basic-auth
Or regular NPM:
npm install tsscmp basic-auth --save
Let's create a new file to modularize our auth middleware. We could just put it all in the same file, but to keep it neat, let's follow the recommended approach to developing Express.js middleware and get started:
// ./server/middleware/auth.js
const auth = require('basic-auth');
const compare = require('tsscmp');
const basicAuth = (request, response, next) => { };
module.exports = basicAuth;
All Express.js middleware follows the same pattern where it's a function that executes with the provided 3 arguments:
request: Express Request objectresponse: Express Response objectnext: function to continueMiddleware can either stop everything by executing a response, or it can allow the application to continue by calling next() which can allow the next middleware (if applicable) or final route handler to run.
// ./server/middleware/auth.js
const auth = require('basic-auth');
const compare = require('tsscmp');
const basicAuth = (request, response, next) => {
const credentials = auth(request);
if (credentials && check(credentials.name, credentials.pass)) {
return next();
}
response.set('WWW-Authenticate', 'Basic realm="my website"');
return response.status(401).send("🙅🏻 nope");
};
module.exports = basicAuth;
This is our basic middleware, where we ask for credentials from the request, which will prompt the user to enter a username and password, then we check those credentials safely using our check() function (that we haven't yet implemented). Upon successful check, we call next() to allow the next middleware (or route handler) to run.
If our check fails, we respond with a 401 Unauthorized.
This is what the check() function looks like:
const compare = require('tsscmp');
const check = (name, pass) => {
let valid = true; // Simple method to prevent short-circuit and use timing-safe compare
valid = compare(name, '[my_username]') && valid;
valid = compare(pass, '[my_password]') && valid;
return valid;
};
It implements tsscmp to safely compare strings.
All together it looks like this:
// ./server/middleware/auth.js
const auth = require('basic-auth');
const compare = require('tsscmp');
const check = (name, pass) => {
let valid = true; // Simple method to prevent short-circuit and use timing-safe compare
valid = compare(name, '[my_username]') && valid;
valid = compare(pass, '[my_password]') && valid;
return valid;
};
const basicAuth = (request, response, next) => {
const credentials = auth(request);
if (credentials && check(credentials.name, credentials.pass)) {
return next();
}
response.set('WWW-Authenticate', 'Basic realm="my website"');
return response.status(401).send("🙅🏻 nope");
};
module.exports = basicAuth;
Then we import it and implement it in our main server file:
const basicAuth = require('./middleware/auth');
app.use(basicAuth);
The final code should look like this:
// ./server/index.js
const express = require('express');
const Path = require('path');
const basicAuth = require('./middleware/auth');
const app = express();
const port = process.env.PORT || 8000;
/**
* Routes
*/
app.use(basicAuth);
app.use('/', express.static(Path.join(__dirname, '../static')));
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});
Now when we run node server/index.js we should have a password-protected server running on port 8000.