Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

How to do authentication and authorization in a Phoenix application with GraphQL

Sean Abrahams edited this page Mar 17, 2016 · 11 revisions

1. Setup plug_graphql

2. If you've haven't already setup authentication for your Phoenix app you will need to create a new plug to set the current_user in conn's assigns map: lib/plugs/authenticate.ex

defmodule YourApp.Plugs.Authenticate do
  import Plug.Conn
  import Phoenix.Controller

  def init(default), do: default

  def call(conn, _default) do
    user_id = get_session(conn, :user_id)
    if user_id do
      user = YourApp.Repo.get!(YourApp.User, user_id)
      assign(conn, :current_user, user)
    else
      conn
        |> put_flash(:error, 'You need to be signed in to view this page.')
        |> redirect(to: "/")
    end
  end
end

3. Update web/router.ex to use the Plug (if you haven't already) and config GraphQL.Plug.Endpoint with the function that will accept conn and return root_value.

  pipeline :api do
    plug :accepts, ["json"]
    plug :fetch_session
    plug YourApp.Plugs.Authenticate ### Require users to be logged in to access API
  end

  scope "/graphql" do
    pipe_through :api

    get "/", GraphQL.Plug.Endpoint, schema: {GraphQL.Schema.Root, :schema}, root_value: {GraphQL.Schema.Root, :root_value}
    post "/", GraphQL.Plug.Endpoint, schema: {GraphQL.Schema.Root, :schema}, root_value: {GraphQL.Schema.Root, :root_value}
  end

4. Create a function that accepts conn and returns a Map for root_value:

defmodule GraphQL.Schema.Root do
  ... other code

  def root_value(conn) do
    %{current_user: conn.assigns[:current_user]}
  end
end

5. Use it

plug_graphql will then make it available in your GraphQL resolve functions (3rd argument) which you can then use for authorization.

For example:

defmodule TestSchema do
  def schema do
    %GraphQL.Schema{
      query: %GraphQL.Type.ObjectType{
        name: "Hello",
        fields: %{
          greeting: %{
            type: %GraphQL.Type.String{},
            args: %{
              name: %{
                type: %GraphQL.Type.String{}
              }
            },
            resolve: fn(obj, args, info) -> 
              ### HERE
              info[:root_value][:current_user]
            end
          }
        }
      }
    }
  end
end
Clone this wiki locally