phoenix, basic auth, environment variables

Add Basic Auth to Phoenix with Environment Variables

There are some situations where you want to block access to an environment such as when you're just staging a project.  

For this particular case, using a custom Basic Auth Plug that's conditional on environment variables may be all you need.

Let's get started by create a custom plug and then "plug" it into our system.

It's assumed that you want to restrict access to the entire application in a staging environment.

Basic Auth Plug

First create WEB/controllers/basic_auth.ex with this content:

(Remember to update MyAppWeb)

defmodule MyAppWeb.BasicAuth do
import Plug.Conn
@realm "Basic realm=\"Staging\""

def init(opts), do: opts

def call(conn, correct_auth) do
case get_req_header(conn, "authorization") do
["Basic " <> attempted_auth] -> verify(conn, attempted_auth, correct_auth)
_ -> unauthorized(conn)

defp verify(conn, attempted_auth, username: username, password: password) do
case encode(username, password) do
^attempted_auth -> conn
_ -> unauthorized(conn)

defp encode(username, password), do: Base.encode64(username <> ":" <> password)

defp unauthorized(conn) do
|> put_resp_header("www-authenticate", @realm)
|> send_resp(401, "unauthorized")
|> halt()


Next, let's add some simple configuration to config/config.ex:

config :my_app, MyAppWeb.BasicAuth, username: "admin", password: "secret"

You can also use environment variables to keep these values out of your repo, but for this simple set up, let's just keep it as is.

Router Conditional

Open WEB/router.ex and add the plug to a pipeline:

  pipeline :browser do
if System.get_env("APP_DOMAIN") == "" do
plug BasicAuth, Application.fetch_env!(:my_app, BasicAuth)

This will check for the value of APP_DOMAIN and conditionally pipe the connection through the custom plug.

NOTE: Don't forget to actually set APP_DOMAIN in your staging environment.

Test Locally

You can optionally test the new Plug out by passing the environment variable's expected value when you start up the Phoenix server:

$ mix -S phx.server

Then you should see the basic auth prompt to enter the credentials.

Wrap up

This was a very simple strategy for restricting access to a staging environment without adding any dependencies.  

This can be expanding and improved upon in many ways but should serve as a basic starting point.


Author image

About Troy Martin

Ruby, Elixir and Javascript Software Developer.