From 9a6b7eb518a2f6f7b466e29addf2545a2db93764 Mon Sep 17 00:00:00 2001 From: njms Date: Tue, 13 Jun 2023 10:07:45 -0700 Subject: [PATCH] Implement authorization plug --- lib/hostas_web/plugs/auth.ex | 54 ++++++++++++++++++++++++++++++++++++ lib/hostas_web/router.ex | 7 +++++ 2 files changed, 61 insertions(+) create mode 100644 lib/hostas_web/plugs/auth.ex diff --git a/lib/hostas_web/plugs/auth.ex b/lib/hostas_web/plugs/auth.ex new file mode 100644 index 0000000..bc852ca --- /dev/null +++ b/lib/hostas_web/plugs/auth.ex @@ -0,0 +1,54 @@ +defmodule HostasWeb.Plugs.Auth do + import Plug.Conn + use HostasWeb, :controller + import Ecto.Query, only: [from: 2] + + alias Hostas.Repo + alias Hostas.Denizen + alias Hostas.Token + + def init(default), do: default + + def call(conn, _default) do + case get_req_header(conn, "authorization") |> List.first() do + nil -> conn + |> put_status(401) + |> json(%{"error" => "No API key provided"}) + |> halt() + header_value -> + case header_value |> String.split() do + [method, key] -> + if method == "Bearer" do + case Token.get(key) do + {:ok, struct} -> + denizen = Repo.one!(from d in Denizen, where: d.id == ^struct.denizen_id) + + conn + |> assign(:token, struct) + |> assign(:denizen, denizen) + {:error, :expired} -> + conn + |> put_status(401) + |> json(%{"error" => "Token expired"}) + |> halt() + {:error, :unknown} -> + conn + |> put_status(401) + |> json(%{"error" => "API key not found"}) + |> halt() + end + else + conn + |> put_status(401) + |> json(%{"error" => "Unknown authorization method"}) + |> halt() + end + _ -> + conn + |> put_status(422) + |> json(%{"error" => "Malformed Authorization header"}) + |> halt() + end + end + end +end diff --git a/lib/hostas_web/router.ex b/lib/hostas_web/router.ex index 9fea092..b4f1680 100644 --- a/lib/hostas_web/router.ex +++ b/lib/hostas_web/router.ex @@ -1,5 +1,6 @@ defmodule HostasWeb.Router do use HostasWeb, :router + alias HostasWeb.Plugs pipeline :browser do plug :accepts, ["html"] @@ -14,6 +15,10 @@ defmodule HostasWeb.Router do plug :accepts, ["json"] end + pipeline :api_locked do + plug Plugs.Auth + end + scope "/", HostasWeb do pipe_through :browser @@ -25,6 +30,8 @@ defmodule HostasWeb.Router do # create, verify, renew, revoke post "/auth/token", Auth.TokenController, :create + + pipe_through :api_locked get "/auth/token", Auth.TokenController, :verify delete "/auth/token/:id", Auth.TokenController, :revoke get "/auth/token/:id/renew", Auth.TokenController, :renew