Securing Ghost with Cloudflare Zero Trust

Cloudflare Zero Trust logo

I really like Ghost as a simple alternative to wordpress. It's sleek, easy to self-host, and just works. But one of my biggest gripes has been the lack of ability to implement MFA. By today's standards, that's usually a deal breaker! However, Cloudflare Zero Trust offers an easy to implement solution to this problem. Let's take a look!

What is Cloudflare Zero Trust?

Cloudflare Zero Trust is a security framework made to protect your online applications by ensuring the only folks who can access your application, or a specific path, are those who you want to have access! As the name suggests, it adopts a zero trust methodology and will always verify access as you as you see fit.

In this case, we will configure Zero Trust to require OTP authentication when trying to access the /ghost path, used to sign into the Ghost blog instance. Note that there are various authentication and identity provider options that can be configured in Zero Trust.  

Prerequisites

To setup Cloudflare Zero Trust, we'll proceed with the following assumptions(links to helpful docs included):

  1. A Cloudflare account is setup.
  2. You have setup a Zero Trust team.
  3. We are setting up the Zero Trust authentication for a self hosted application.
  4. The self hosted application already uses Cloudflare for DNS.

Let's Go

Login to your Cloudflare account and go to Zero Trust.

Cloudflare dashboard, highlighting the Zero Trust menu option.

Go to applications.

Zero Trust overview page, highlighting the Applications menu option.

Let's add our application.

Zero Trust applications page, highlighting the "Add an Application" button.

Our application is self hosted.

Selecting the self hosted application option.

I'm going to call the application "ghost" and set the session duration to 6 hours. Once authenticated, the user will not have to re-authenticate for that duration. Let's set the path to /ghost. Any resources contained within /ghost/* will require authentication.

Configuring path and authentication options.

Let's setup our policy. We'll create a policy named "ghost_auth" which will allow users who successfully authenticate access for the previously specified duration. We will configure two rules. The first, we will specify that we want to use one-time-pin (OTP) authentication. The second, will let us define the email addresses that are allowed to receive the OTP's. Only the email addresses specified here can receive a pin.

Policy setup page.

The last page of the application setup goes over CORS options and Cookie settings - the defaults are ok for now. Same applies for the additional settings not mentioned in previous steps. For our purposes, the defaults are fine. It's time to click "Add application."

Voila!

If we navigate to the /ghost path for our blog, where we would usually sign in, we are first greeted with a prompt to enter our email for OTP authentication. Reminder: only the email addresses added to our policy rules will receive a code.

Cloudflare Zero Trust prompt asking for an email address.

Once you enter a valide email address, you wil receive the OTP code.

Cloudflare Zero Trust prompt asking for OTP code.

We can enter the OTP code, click sign in, and then be presented with the usual Ghost blog sign in prompt. From there, you would sign in with your email/password as usual.

In conclusion, while it is disappointing that Ghost has yet to implement MFA out of the box, Cloudflare Zero Trust provide a practival, and easy to implement, solution to mitigating those concerns.