Packages
blossom
0.6.2
0.29.3
0.29.2
0.29.1
0.29.0
0.28.0
0.27.3
0.27.2
0.27.1
0.27.0
0.26.3
0.26.2
0.26.1
0.26.0
0.25.3
0.25.2
0.25.1
0.25.0
0.24.1
0.24.0
0.23.5
0.23.4
0.23.3
0.23.2
0.23.1
0.23.0
0.22.1
0.22.0
0.21.8
0.21.7
0.21.6
0.21.5
0.21.4
0.21.3
0.21.2
0.21.1
0.21.0
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.15.2
0.15.1
0.15.0
0.14.0
0.13.0
0.12.2
0.12.1
0.12.0
0.11.0
0.10.1
0.10.0
0.9.2
0.9.1
0.9.0
0.8.0
0.7.0
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Easy identity for easy authentication
Current section
Files
Jump to
Current section
Files
lib/blossom/auth_plug.ex
defmodule Blossom.AuthPlug do
alias Blossom.{AuthPlug, 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 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]),
expiration: Utils.expiration(config, options),
jwt_key: AuthPlug.jwt_key(config, options),
realm: AuthPlug.realm(config, options, options[:otp_app]),
secret: Utils.secret(config, options),
users_controller: AuthPlug.users_controller(config, options),
user_key: AuthPlug.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 AuthPlug.get_header(conn) do
nil -> {:error, :no_authorization_header}
header -> AuthPlug.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
conn
|> AuthPlug.unauthorized_header(error, opts[:realm])
|> Conn.put_resp_content_type("application/json")
|> Conn.send_resp(401, Poison.encode!(%{"message" => error}))
|> Conn.halt()
end
def get_user(controller, user_id) do
params = %{"id" => user_id, "blocked" => false}
case controller.get(params, :public) do
[] -> {:error, :unknown_user}
[user] -> {:ok, user}
end
end
def put_user(conn, fields, opts) do
case AuthPlug.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} ->
AuthPlug.send_401(conn, error, opts)
end
end
def put_private(outcome, conn, opts) do
case outcome do
{:ok, fields} -> AuthPlug.put_user(conn, fields, opts)
{:error, error} -> AuthPlug.send_401(conn, error, opts)
end
end
def handle_auth(outcome, conn, opts) do
case outcome do
{:ok, token} ->
token
|> Tokens.verify(opts)
|> AuthPlug.put_private(conn, opts)
{:error, error} ->
AuthPlug.send_401(conn, error, opts)
end
end
def call(conn, options) do
opts = AuthPlug.get_opts(options)
conn
|> AuthPlug.get_token()
|> AuthPlug.handle_auth(conn, opts)
end
end