Absinthe: Remove a default middleware on specific resolvers

Reading through the Absinthe Graphql book, written by the library’s author, you can add middleware to ALL routes, or all mutations or all queries:

  def middleware(mw, _field, _obj) do
    mw ++ [Authentication]
  end

This adds the authentication middleware to every single field and object requested in GQL.

The question is, is there a way to keep this as the default, but REMOVE it in some scenarios? (i.e. a registration mutation).

Something like (this doesn’t work as I would hope):

  # Don't apply Authentication middlewear to auth_mutations
  def middleware(mw, _field, %{identifier: :auth_mutations}) do
    mw
  end

  # All graphql routes require authentication
  def middleware(mw, _field, _obj) do
    mw ++ [Authentication]
  end

This is a very old thread, but it’s the a top Google search result for this so I figured I’d drop an answer here (apologies if this was not desired!):

I ran into this same issue and eventually realized you can check the identifier of the field. For instance:

  def middleware(middleware, field, obj) do
    if obj.identifier in [:query, :subscription, :mutation] &&
         field.identifier not in [:authenticate, :refresh] do
      [CrystifiWeb.Schema.Middleware.RequireAuth | middleware]
    else
      middleware
    end
  end

This will not authenticate the :authenticate and :refresh mutations. (This actually won’t authenticate anything named :authenticate and :refresh, but the reasons are pretty evident, and I admittedly didn’t feel like fixing up this example code…)

4 Likes

It’s appreciated! I ended up just doing a basic json endpoint to handle non auth stuff, but I’d love to dive back in and see how this works!

1 Like

Another possibility might be to still apply the middleware everywhere but have that middleware check a field’s metadata to determine if auth should be disabled. For example, an auth-less field could have meta :no_auth, true in the schema you define. That “meta” macro is built into absinthe.

It could have the advantage of not hard coding the exception list in your middleware, plus you get to express the “don’t auth this” instruction in your schema itself which might make it easier to understand later.

4 Likes

This actually looks perfect, slightly surprised the docs didn’t mention it (a Google search actually shows this very topic on the first page of results).

As a fun extra bit with this: If you set it via meta you can actually look for that meta flag in the def middleware/3 function, which will then avoid even the runtime overhead.

1 Like