Recently I had the opportunity to study security best practices for GraphQL. One security recommendation that stood out as low-hanging fruit was disabling GraphQL introspecting for your API in production. GraphQL libraries I have used for Ruby and JavaScript made doing this very easy, so I was expecting the same thing with the Absinthe library in Elixir. It then surprised me that disabled introspection in Absinthe was documented, and every more confusing to figure out how.
Luckily after some web searching, I stumbled upon a Gist made by the community with middleware to disable introspection. So for my own implementation, I decided to make it simpler and disable introspection entirely if you are not in the development environment. Check it out.
defmodule MyAppWeb.Schema.Middleware.AuthorizedIntrospection do
@moduledoc """
Disable schema introspection outside of development
"""
@behaviour Absinthe.Plugin
@impl Absinthe.Plugin
def before_resolution(exec) do
if Enum.find(exec.result.emitter.selections, fn %{name: field_name} ->
Macro.underscore(field_name) == "__schema" && Mix.env() != :dev
end) do
%{
exec
| validation_errors: [
%Absinthe.Phase.Error{message: "Unauthorized", phase: __MODULE__}
]
}
else
exec
end
end
@impl Absinthe.Plugin
def after_resolution(exec), do: exec
@impl Absinthe.Plugin
def pipeline(pipeline, _exec), do: pipeline
end
Top comments (1)
Note that Mix.env is not available in releases.
See hexdocs.pm/mix/Mix.html#env/0