DEV Community

Erik Guzman
Erik Guzman

Posted on • Updated on

TIL: Disabling introspection in prod for Absinthe

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
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
maartenvanvliet profile image
Maarten van Vliet

Note that Mix.env is not available in releases.

See hexdocs.pm/mix/Mix.html#env/0