...

/

Middleware Authorization

Middleware Authorization

Learn how to add authorization checks using middleware.

Authorization middleware

Adding authorization checks inside all our resolvers will produce clutter, so let’s build middleware to handle this problem fully. As you may recall, we have two choices for how to apply middleware:.We can use the middleware/2 macro to configure individual fields or the middleware/3 callback function to take a pattern-based approach. Different fields have slightly different authorization conditions, so we will use the middleware/2 macro to annotate them individually. Using this middleware should look something like this:

Press + to interact
field :create_menu_item, :menu_item_result do
arg :input, non_null(:menu_item_input)
middleware Middleware.Authorize, "employee"
resolve &Resolvers.Menu.create_item/3
end

Then, in the resolver, we can just go back to how it was before the authorization check:

Press + to interact
def create_item(_, %{input: params}, _) do
with {:ok, item} <- Menu.create_item(params) do
{:ok, %{menu_item: item}}
end
end

Note: We no longer need to check the type of the current_user in the resolution function or handle the possibility that there is no current_user at all. The middleware will handle all of this for us.

Press + to interact
defmodule PlateSlateWeb.Schema.Middleware.Authorize do
@behaviour Absinthe.Middleware
def call(resolution, role) do
with %{current_user: current_user} <- resolution.context,
true <- correct_role?(current_user, role) do
resolution
else
_ ->
resolution
|> Absinthe.Resolution.put_result({:error, "unauthorized"})
end
end
defp correct_role?(%{}, :any), do: true
defp correct_role?(%{role: role}, role), do: true
defp correct_role?(_, _), do: false
end

By specifying @behaviour ``Absinthe.Middleware, the compiler will ...