Protecting Phoenix endpoints with HTTP Basic Auth (on Heroku)

Phoenix LiveDashboard was recently officially announced by José Valim, and I was keen try it out so I installed it on a toy app I've been developing, which is deployed to Heroku.

I didn't want my LiveDashboard to be available to the whole world, so the quickest and easiest method of protecting it was to use HTTP Basic Authentication, something that is recommended in the LiveDashboard docs.

To that end, I installed and configured the basic_auth plug, and read the username and password to configure it from environment variables.

These are the steps I took.

Install and configure basic_auth

1. Add the basic_auth plug

Add basic_auth to your mix.exs file

1
{:basic_auth, "~> 2.2.4"}

Install dependencies

1
mix deps.get

2. Configure basic_auth from environment variables

Edit your prod.secret.exs file and add this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
http_basic_auth_username =
  System.get_env("HTTP_BASIC_AUTH_USERNAME") ||
    raise """
    environment variable HTTP_BASIC_AUTH_USERNAME is missing.
    """

http_basic_auth_password =
  System.get_env("HTTP_BASIC_AUTH_PASSWORD") ||
    raise """
    environment variable HTTP_BASIC_AUTH_PASSWORD is missing.
    """

# Set basic auth from environment variables
config :example_web, basic_auth: [
  username: http_basic_auth_username,
  password: http_basic_auth_password,
]

3. Update the router to protect the LiveDashboard routes

Create a new pipeline that conditionally adds the basic_auth plug if the HTTP_BASIC_AUTH_USERNAME or HTTP_BASIC_AUTH_PASSWORD are present.

1
2
3
4
5
pipeline :protected do
  if System.get_env("HTTP_BASIC_AUTH_USERNAME") || System.get_env("HTTP_BASIC_AUTH_PASSWORD") do
    plug BasicAuth, use_config: {:example_web, :basic_auth}
  end
end

Then add :protected to the pipeline.

1
2
3
4
scope "/", ExampleWeb do
  pipe_through [:browser, :protected]
  live_dashboard "/dashboard"
end

4. Set your environment variables on Heroku

1
2
heroku config:set HTTP_BASIC_AUTH_USERNAME=admin \
                  HTTP_BASIC_AUTH_PASSWORD=P@ssword

Now when you visit /dashboard you should be prompted to enter your username and password.