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)
end
end

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

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

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

Configuration

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") == "staging.myapp.com" do
plug BasicAuth, Application.fetch_env!(:my_app, BasicAuth)
end
end

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:

$ APP_DOMAIN=staging.myapp.com 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.