Integration with Auth (Guardian)
naderhen opened this issue · 3 comments
I'm attempting to access the currently logged in user during GraphQL resolves. Looking at the pull-request history (specifically #9, it seems I should be able to inject whatever data I need via the root_value so I've defined a module like so:
defmodule MyApp.GraphQLSession do
def root_eval(_conn) do
%{conn: _conn}
end
end
and amended my api pipeline to:
pipeline :api do
plug :accepts, ["json"]
plug Guardian.Plug.VerifyHeader
plug Guardian.Plug.LoadResource
plug GraphQL.Plug.Endpoint, [schema: {GraphQL.Schema.EctoWorld, :schema}, root_value: &MyApp.GraphQLSession.root_eval/1]
end
scope "/graphql" do
pipe_through :api
get "/ecto", GraphQL.Plug, schema: {GraphQL.Schema.EctoWorld, :schema}
post "/ecto", GraphQL.Plug, schema: {GraphQL.Schema.EctoWorld, :schema}
end
scope "/api", MyApp do
pipe_through :api
....
post "/registrations", RegistrationController, :create
post "/sessions", SessionController, :create
delete "/sessions", SessionController, :delete
get "/current_user", CurrentUserController, :show
....
end
Note: I'm using Guardian for authentication.
However, whenever I try and hit any endpoint (either via GraphiQL or curl) an exception is raised:
(Plug.Conn.AlreadySentError) the response was already sent
I'm sure I'm missing something fairly simple as I've just started learning Elixir/Phoenix. I was hoping to get any insight into this or perhaps a working example of integrating GraphQL with Guardian.
Please let me know if there is any more information I can provide.
Thanks!
@naderhen The GraphQL plug should only be forwarded to for certain endpoints using forward, or a combination of get and post. Check out these examples.
The reason you are probably getting an error is because the plugs are stepping on each other. What I'm speculating is that the Guarding plug is forcing a halt on the connection and then the GraphQL plug has already sent back data in the response as you have it getting executed on each request.
In the end you will want something like:
scope "/graphql" do
pipe_through :api
forward "/", GraphQL.Plug.Endpoint, [
schema: { GraphQL.Schema.EctoWorld, :schema },
root_value: {MyApp.GraphQLSession, :root_value} ]
endIf you are running inside of Phoenix, you should use the {mod, :fun} syntax so that Phoenix can properly do live code reloading.
Wow, that fixed it. Thanks so much!
If you only have a single GraphQL endpoint then forward is the preferred approach.
Please post any other questions, we'd love to include some Guardian examples also!