Current section

Files

Jump to
blossom lib blossom plugs put_auth.ex
Raw

lib/blossom/plugs/put_auth.ex

defmodule Blossom.Plugs.PutAuth do
alias Blossom.Plugs.PutAuth
alias Blossom.{Tokens, Utils}
alias Plug.Conn
def users_controller(config, opts) do
Utils.option_or_key_config(config, opts, :users_controller, nil)
end
def jwt_key(config, opts) do
Utils.option_or_key_config(config, opts, :jwt_key, :jwt)
end
def realm(config, opts, otp_app) do
Utils.option_or_key_config(config, opts, :realm, otp_app)
end
def user_key(config, opts) do
Utils.option_or_key_config(config, opts, :user_key, :user)
end
def enforce_auth(config, opts) do
Utils.option_or_key_config(config, opts, :enforce_auth, true)
end
def init(opts), do: opts
def get_opts(options) do
config = Application.get_env(options[:otp_app], Blossom)
[
audience: Utils.audience(config, options, options[:otp_app]),
enforce_auth: PutAuth.enforce_auth(config, options),
expiration: Utils.expiration(config, options),
jwt_key: PutAuth.jwt_key(config, options),
realm: PutAuth.realm(config, options, options[:otp_app]),
secret: Utils.secret(config, options),
users_controller: PutAuth.users_controller(config, options),
user_key: PutAuth.user_key(config, options)
]
end
def get_header(conn) do
List.first(Conn.get_req_header(conn, "authorization"))
end
def token_from_header(header) do
fragments = String.split(header)
if String.downcase(List.first(fragments)) == "bearer" do
{:ok, List.last(fragments)}
else
{:error, :no_bearer_token}
end
end
def get_token(conn) do
case PutAuth.get_header(conn) do
nil -> {:error, :no_authorization_header}
header -> PutAuth.token_from_header(header)
end
end
def unauthorized_header(conn, error, realm) do
conn
|> Conn.put_resp_header(
"www-authenticate",
"Bearer realm=\"#{realm}\", error=\"#{error}\""
)
end
def send_401(conn, error, opts) do
if opts[:enforce_auth] == false do
conn
else
conn
|> PutAuth.unauthorized_header(error, opts[:realm])
|> Conn.put_resp_content_type("application/json")
|> Conn.send_resp(401, Poison.encode!(%{"message" => error}))
|> Conn.halt()
end
end
def get_user(controller, user_id) do
params = %{"id" => user_id, "blocked" => false}
case controller.get(params, :system) do
[] -> {:error, :unknown_user}
[user] -> {:ok, user}
end
end
def put_user(conn, fields, opts) do
case PutAuth.get_user(opts[:users_controller], fields["sub"]) do
{:ok, user} ->
conn
|> Conn.put_private(opts[:jwt_key], fields)
|> Conn.put_private(opts[:user_key], user)
{:error, error} ->
PutAuth.send_401(conn, error, opts)
end
end
def put_private(outcome, conn, opts) do
case outcome do
{:ok, fields} -> PutAuth.put_user(conn, fields, opts)
{:error, error} -> PutAuth.send_401(conn, error, opts)
end
end
def handle_auth(outcome, conn, opts) do
case outcome do
{:ok, token} ->
token
|> Tokens.verify(opts)
|> PutAuth.put_private(conn, opts)
{:error, error} ->
PutAuth.send_401(conn, error, opts)
end
end
def call(conn, options) do
opts = PutAuth.get_opts(options)
conn
|> PutAuth.get_token()
|> PutAuth.handle_auth(conn, opts)
end
end