HUIJZER.XYZ

Static site authentication

2022-02-16

More and more companies start providing functionality for static site hosting. For example, GitHub announced Pages in 2008, Netlify was founded in 2014, GitLab annouced pages in 2016 and Cloudflare launched a Pages beta in 2020. Nowadays, even large general cloud providers, such as Digital Ocean, Google, Microsoft or Amazon, have either dedicated products or dedicated tutorials on static site hosting.

In terms of usability, the products score similarly. Setting up hosting usually involves linking a Git account to a hoster which will allow the hoster to detect changes and update the site based on the latest state of the repository. In terms of speed, the services are also pretty similar.

In terms of authentication, however, the products score differently. This blog post will walk through my experiences with private static sites.

Basic access authentication

First a remark on basic auth, also known as HTTP Basic authentication (BA). A worry can be that basic auth sends the credentials as cleartext. Nowadays, this is not such a big problem anymore since it can be mitigated by forcing HTTPS and today's browsers give clear warnings in the case of basic auth via HTTP. Still, it is usually advised to avoid basic auth because there is no clear logout mechanism. Most people do not know how to logout from basic auth, so this can cause unauthorized access when another person gets access to the system. For the interested reader: to logout from basic auth, click on the lock before the url in your browser and click on clear cookies. Also, sessions are generally preferred over passwords since having a password allows access until a password is reset whereas sessions time out after a certain period.

.htaccess

Secondly, a remark on .htaccess since this discussion comes up every time someone mentions authentication. .htaccess is a configuration file for Apache Web Servers which allows includes settings for password protection. That this method is based on a file is a problem in the case of static site hosters. Most most static site hosters assume that the to-be-published files are in a repository, so therefore using a .htaccess file means having to store secrets as text inside the repository. This is a problem. Also, .htaccess is based on passwords and not sessions which is a problem as is discussed above. So, in general, it is best to avoid using .htaccess files for static sites. This is also probably why most hosters do not support .htaccess.

GitLab Pages

As far as I know, GitLab Pages is the easiest to setup. The service requires a free GitLab account and allows setting a complete web site to private. To configure access, specify one or more GitLab users and for how long they have access. Overall, I would say this is a great service. Unfortunately, in my case, not all readers had a GitLab account and the pages had a latency of 1-2 seconds upon each request (which may of course be fixed at the time of reading). That is why I switched to Netlify.

Netlify

Netlify offers two ways of authentication, namely a password / JWT secret or OAuth. This does require a Pro plan, which is 19 dollar per member per month at the time of writing. In about 40 minutes, I wasn't able to configure OAuth so I gave up on that and used password protection. This only allows setting one password for the whole site which is problematic when multiple people should get access. When multiple people share the same password, it is not possible to deny access to one person without changing the password for everyone. Irregardless of that minor problem which can probably be solved by taking another look at the OAuth feature, there is also the page loading speed problem here. Just like GitLab, each page had a latency of 1-2 seconds upon each request. Somewhere on a forum, I read that this is because Netlify uses only one server for password protected sites versus their usual content delivery network (CDN). I've tested from the Netherlands, so maybe the speed is better if you happen to live in the US. I didn't investigate this further because overall the service is pretty limited for 19 dollar per month. Hence, I started looking for alternatives again.

Cloudflare

At the time of writing, I just moved to Cloudflare and I must say that this feels the most capable in regards to speed and security. In regards to the price, authentication is part of the free plan so that's great. The speed is excellent and logging in is possible via a One-time PIN and a Google ID and more providers are possible but these are the two that I've used. Setting up authentication for a Cloudflare Pages site was a bit tricky. In the last part of this post, I'll walk through the configuration steps for setting up a private static website with a custom domain. Including the time needed to verify everything, this should take about an hour.

Let's say that we're registering a https://protected.example.com. The workflow is as follows:

  1. Add a new Pages site and but don't put sensitive information on it yet. You can add access security policies in later steps. Say that the domain is protected.2252142.pages.dev.

  2. After deployment, go to settings and click on "Enable Access Policy" for the Preview deployments. This adds an access policy to the Cloudflare Zero Trust environment at url *.protected-2252142.pages.dev, see below for more information.

  3. Add an extra policy for the main deploys at protected.2252142.pages.dev.

Now, you should have the following Applications URLs listed under Access in Cloudflare Zero Trust. The names are arbitrary; I've added some suggestions below. Correctness of the Policies and URLs is the most important.

Application nameApplication URLType
protected.example.com - Previews*.protected.2252142.pages.devself-hosted
protected.example.com - Pagesprotected.2252142.pages.devself-hosted

Please verify these settings for yourself after setting up your site. Once everything looks good, you can add your custom domain via the Pages settings. Now, logging in will not work yet for protected.example.com because a callback is missing. To fix this, we have to add an Application URL for the custom domain too, which gives as end-result:

Application nameApplication URLType
protected.example.com - Previews*.protected.2252142.pages.devself-hosted
protected.example.com - Pagesprotected.2252142.pages.devself-hosted
protected.example.comprotected.example.comself-hosted

And again, please verify that everything is correct by trying to login to the different domains in the incognito mode of your browser.

In conclusion, compared to my previous Netlify setup, the end-result is now more quick, more secure, cheaper and easier to use.