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 16, 2016 · 11 revisions

1. Setup plug_graphql

2. Create a new plug: 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)
      conn = assign(conn, :current_user, user)
      # Set user in conn.assigns.graphql_options for GraphQL queries/mutations
      # graphql_plug will look for `conn.assigns[:graphql_options][:root_value]` and include it in the GraphQL context variable
      graphql_options = Map.merge(conn.assigns[:graphql_options] || %{}, %{ root_value: %{ user: user } })
      conn = assign(conn, :graphql_options, graphql_options)
      conn
    else
      conn
        |> put_flash(:error, 'You need to be signed in to view this page.')
        |> redirect(to: "/")
    end
  end
end

This plug will redirect users who are not logged in (don't have a :user_id set in their session) to your root page with a flash error message.

Users who are logged in will have their user object added to the conn[:assigns] map and the conn[:assigns][:graphql_options][:root_value]. We add it to the conn[:assigns][:graphql_options][:root_value] map because that's where plug_graphql needs it to be.

3. Add the plug to your API pipeline in web/router.ex

  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}
    post "/", GraphQL.Plug.Endpoint, schema: {GraphQL.Schema.Root, :schema}
  end

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][:user]
            end
          }
        }
      }
    }
  end
end
Clone this wiki locally