Packages

What if GitHub gists, AWS Lambdas and Elixir Plugs had a baby?

Current section

Files

Jump to
vik lib vik_web auth.ex
Raw

lib/vik_web/auth.ex

defmodule VikWeb.Auth do
@moduledoc false
use VikWeb, :plug
@realm "Vik"
import Plug.Crypto, only: [secure_compare: 2]
import Plug.BasicAuth, only: [parse_basic_auth: 1, request_basic_auth: 2]
def on_mount(mode, params, session, socket) do
case Application.fetch_env!(:vik, :auth) do
:nym -> Nym.on_mount(mode, params, session, socket)
:basic -> mount_basic_auth(mode, params, session, socket)
end
end
def fetch_current_user(conn, opts) do
case Application.fetch_env!(:vik, :auth) do
:nym -> Nym.fetch_current_user(conn, opts)
:basic -> fetch_basic_auth(conn, opts)
end
end
def require_auth(conn, opts) do
case Application.fetch_env!(:vik, :auth) do
:nym -> Nym.require_auth(conn, opts)
:basic -> require_basic_auth(conn, opts)
end
end
defp mount_basic_auth(:default, _params, session, socket) do
username = Map.get(session, "current_user")
{:cont, socket
|> Phoenix.Component.assign(:current_user, username)
|> Phoenix.Component.assign(:authenticated?, not is_nil(username))}
end
@spec fetch_basic_auth(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t()
defp fetch_basic_auth(conn, _opts) do
case validate_credentials(conn) do
{:ok, username} -> log_in(conn, username)
:error -> conn |> renew_session() |> log_in(nil)
end
end
@spec require_basic_auth(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t()
defp require_basic_auth(conn, _opts) do
if conn.assigns.current_user do
conn
else
conn |> request_basic_auth(realm: @realm) |> halt()
end
end
defp validate_credentials(conn) do
app_password = Application.fetch_env!(:vik, :password)
with {username, password} <- parse_basic_auth(conn) do
if secure_compare(password, app_password) do
{:ok, username}
else
:error
end
end
end
defp log_in(conn, username) do
conn
|> assign(:current_user, username)
|> put_session(:current_user, username)
end
# This function renews the session ID and erases the whole
# session to avoid fixation attacks. If there is any data
# in the session you may want to preserve after log in/log out,
# you must explicitly fetch the session data before clearing
# and then immediately set it after clearing.
defp renew_session(conn) do
delete_csrf_token()
conn
|> configure_session(renew: true)
|> clear_session()
end
end