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.
Wrapping 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.