Authenticated and Unauthenticated "Endpoints" with Elixir and Absinthe

I have a scenario where I want one GraphQL resolver to be reached without first being authenticated (The Sign In Endpoint). But I can’t figure out how to separate the the authenticated and unauthenticated routes.

Here is my router:

ROUTER:

  scope "/graphql/unauthenticated" do
    pipe_through([:api])

    forward "/", Absinthe.Plug, schema: StatcastersWeb.Schema
  end

  scope "/graphql" do
    pipe_through([:api, :authenticated])

    forward "/", Absinthe.Plug, schema: StatcastersWeb.Schema
  end

ERROR:

Absinthe.Plug has already been forwarded to. A module can only be forwarded a single time.

I understand the error, but what do I do here? I want to have a place to tell GraphQL that this query doesn’t need to be authenticated. How can I achieve this?

2 Likes

This is a Phoenix router limitation. Fortunately it’s pretty easy to work around, we can just create an interstitial module that wraps Absinthe.Plug

defmodule My.Absinthe.Plug do
  defdelegate init(opts), to: Absinthe.Plug
  defdelegate call(conn, opts), to: Absinthe.Plug
end

Then you can just do forward "/", My.Absinthe.Plug, schema: ... for one of them and it’ll be fine.

16 Likes

Perfect. Thanks for the help, Ben.

I hit the same problem. Thanks for the workaround. But why Phonix router intro this limitation?

Is this workaround still working? I getting this error

My.Absinthe.Plug has already been forwarded to. A module can only be forwarded a single time.

Hi @apellizzn can you show your router code? If I had to guess you’re forwarding to the new plug in both cases when you should be forwarding to the normal plug once, and your new plug once.

1 Like