> tail -f adding-basic-auth-to-a-static-cloudflare-page

Adding Basic Auth to a Static Cloudflare Page

cloudflare-pages-logo.png
cloudflare-pages-logo.png (image/png)

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!