· engineering · 4 min read
Basic Authentication for free with Netlify edge functions
How to use Netlify edge functions to password-protect your staging site on the free plan.
Table of Contents
This site is hosted on Netlify, initially prompted by my interest in using Decap CMS, which integrates smoothly with Netlify and Astro.
Of course I needed a staging version, but to my surprise, Netlify’s authentication features were limited to paid plans. However, Netlify does offer edge functions…
What Are Edge Functions?
Edge functions allow developers to execute code as traffic enters or leaves your Content Delivery Network (CDN). The functions Netlify offers are similar to AWS CloudFront’s Lambda@Edge, which allows code execution at the edge of the network, but optimized and simplified for specific uses like A/B testing, adding live data, or, in our case, adding Authentication.
Using edge functions, we can implement Basic Access Authentication — a simple, though not very secure, method of authentication. Credentials are sent as base64 encoded strings in every request’s header, making HTTPS essential to protect against middleman attacks. Ensure you have a valid SSL certificate for your staging site. This method suits our staging environment perfectly since it doesn’t require sessions, cookies, or login pages.
For production environments, consider using a more secure authentication method like JWTs (JSON Web Tokens).
Implementing Basic Access Authentication
First, a word of warning on basic authentication: while it is straightforward to implement, it should not be used for any sensitive data as it only provides minimal security and is vulnerable to interception.
That said, it does provide adequate protection to gate off a staging site.
Here’s how you can set up Basic Access Authentication using an edge function saved in “./netlify/edge-functions”, the default location for Netlify to look for edge functions.
Explanation: The code is pretty simple.
We’re just looking for an authHeader, and checking it matches the expected value.
If its absent, or incorrect, we return a 401 response and a header instructing the browser to request Basic Access Authentication credentials. If the credentials match OR there are no credentials configured, then we return the normal response.
The only slightly unusual aspect is the workaround for environment variables, presumably necessary because AWS Lambda@Edge, which Netlify is built on, does not support them.
Configuring netlify
I started off trying to set my site up as a single site in Netlify, but limitations of the free plan made this rather convoluted.
I have Netlify set up as follows:
- Two individual sites. one for staging, one for production - this allows me to configure each separately, and enable features (like Identity for DecapCMS just on staging).
- On the staging site, I have configured “BASIC_USERNAME” and “BASIC_PASSWORD”; on the prod one, I haven’t.
- Each deploys a different branch of my repository.
- we add the following section to our
netlify.toml
. This instructs Netlify to use our edge function for all paths EXCEPT those beginning with .netlify as these are used with Netlify identity services, which, at the time of writing, I was attempting to use for DecapCMS.
This is enough to have Basic Access Authentication working on staging, and disabled on production.
One last improvement
We do now have Basic Access Authentication on staging and not on production, and so we have a simple way of password protecting our staging site.
However, the edge function is still being executed on every request to production, and there is a (generous) limit to the amount of executions the free plan allows.
Ideally we would remove the edge function entirely for production.
A quick and simple work-around for this is:
- create two
netlify.toml
files: one for staging and one for production. - Adjust the
package.json
scripts to rename the appropriate configuration file during the build: - On the production site, go to Site Configuration > Build & Deploy > Continuous Deployment and change the value of Build command to
npm run build:prod
This setup ensures your staging environment is (somewhat) secure and not indexed by search engines, while keeping production streamlined and free from unnecessary function executions.
About James Babington
A cloud architect and engineer with a wealth of experience across AWS, web development, and security, James enjoys writing about the technical challenges and solutions he's encountered, but most of all he loves it when a plan comes together and it all just works.
No comments yet. Be the first to comment!