Archive / 2025

Adding Basic Auth to a Static Cloudflare Page

This tutorial covers how to add basic auth to a Cloudflare page endpoint, and how to add it to the entire site or a specific endpoint.

Cloudflare Pages authentication diagram

1. Why Add Basic Auth to a Static Cloudflare Page?

As a remote software developer, I know how we frequently need to access and make tools to make our work easier, and how important it is to share this with our colleagues, however I also sometimes don’t want to share these with the entire world, and the dreaded AI scrapers. It’s also extremely convenient for sites like this, where it was created using a CI pipeline, but I don’t want it to be accessible until it was complete, hence the need for basic auth.

2. What You’ll Need Before Getting Started

  • A git repository
  • A cloudflare account, with workers enabled
  • An IDE and Website

3. Creating the Functions Folder in Your Static Project

The way this script works is using a tool in Cloudflare called Cloudflare Functions which allows a serverless site to run with middleware. To set this up, in the root folder of your repository create a /functions folder, which will be automatically picked up by Cloudflare when deployed.

4. Adding Middleware to Protect Specific Routes

After making the functions folder, you can make an _middleware.js file, which basically applies the code to the entirety of the website (don’t worry we will add specifc paths later!)

5. Implementing Basic Auth in Cloudflare Pages

This code should then be added to your _middleware.js file.

export async function onRequest(context) {
  const USERNAME = context.env.AUTH_USER || "admin";
  const PASSWORD = context.env.AUTH_PASS || "secret";

  const url = new URL(context.request.url);
    if (!authHeader || !checkAuth(authHeader, USERNAME, PASSWORD)) {
      return new Response("Authentication required", {
        status: 401,
        headers: {
          "WWW-Authenticate": 'Basic realm="Protected Area"',
        },
      });
    }
  }

  return context.next();
}

function checkAuth(header, username, password) {
  const encoded = header.replace("Basic ", "");
  const decoded = atob(encoded);
  const [user, pass] = decoded.split(":");
  return user === username && pass === password;
}

In your Cloudflare Page you should then add in two env variables, one for the username with the name as AUTH_USER and the password should also be added in as AUTH_PASS.

Cloudflare ENV Dashboard

6. Protect specific endpoints

To protect a specifc endpoint like /admin you must update your _middleware.js to contain this:

export async function onRequest(context) {
  const USERNAME = context.env.AUTH_USER || "admin";
  const PASSWORD = context.env.AUTH_PASS || "secret";

  const url = new URL(context.request.url);

  // Only protect /admin and subpaths
  if (url.pathname.startsWith("/admin")) {
    const authHeader = context.request.headers.get("Authorization");

    if (!authHeader || !checkAuth(authHeader, USERNAME, PASSWORD)) {
      return new Response("Authentication required", {
        status: 401,
        headers: {
          "WWW-Authenticate": 'Basic realm="Protected Area"',
        },
      });
    }
  }

  return context.next();
}

function checkAuth(header, username, password) {
  const encoded = header.replace("Basic ", "");
  const decoded = atob(encoded);
  const [user, pass] = decoded.split(":");
  return user === username && pass === password;
}

7. Final Thoughts

I hope this helped, and if you have any questions about it or need a hand don’t hesitate to email blog@bizbazboz.uk for assitance!