defmodule SyntropyWeb.Plugs.ApiAuth do @moduledoc """ Enforces Syntropy external API auth when token auth is enabled. Each API pipeline declares its scope class: plug SyntropyWeb.Plugs.ApiAuth, scope: :read Missing or invalid tokens answer 401; valid tokens without the required scope answer 403. """ import Plug.Conn import Phoenix.Controller, only: [json: 2] alias SyntropyWeb.ApiAuth @spec init(keyword()) :: ApiAuth.scope() def init(opts), do: Keyword.get(opts, :scope, :admin) @spec call(Plug.Conn.t(), ApiAuth.scope()) :: Plug.Conn.t() def call(conn, required_scope) do case ApiAuth.validate_conn(conn, required_scope) do {:ok, scope} -> assign(conn, :api_scope, scope) {:error, {:insufficient_scope, _scope} = reason} -> conn |> put_status(:forbidden) |> json(%{ error: %{ code: "forbidden", message: ApiAuth.error_message(reason) } }) |> halt() {:error, reason} -> conn |> put_status(:unauthorized) |> json(%{ error: %{ code: "unauthorized", message: ApiAuth.error_message(reason) } }) |> halt() end end end