Screencast

25. GraphQL with Phoenix and Absinthe

absinthe api graphql jwt

A tutorial that shows how to add a flexible GraphQL API to your Phoenix application with Absinthe. Learn how to expose your Ecto resources through a GraphQL endpoint, handle authentication with JWT tokens, and implement secured CRUD operations.

Whether you have an existing application with authentication or are starting from scratch, this tutorial will guide you through all the necessary steps. By the end, you'll have a GraphQL API that can be used alongside your regular Phoenix endpoints.

Setting up GraphQL Schema in Phoenix

A GraphQL schema acts as a contract between your API and clients, defining what queries and data types are available. With Absinthe, you can easily map your existing Ecto schemas to GraphQL types, making it straightforward to expose your data through a GraphQL API. In the video, I'll show you how to set up a complete schema with proper documentation that clients can explore through GraphiQL.

defmodule TutorialWeb.Schema.BreweryTypes do
  use Absinthe.Schema.Notation

  @desc "A brewery"
  object :brewery do
    field :id, :id
    field :name, :string
    field :state, :string
    field :city, :string
  end

  object :get_breweries do
    field :breweries, list_of(:brewery) do
      resolve(&Resolvers.Breweries.list_breweries/2)
    end
  end
end

Authentication with GraphQL Mutations

Instead of traditional REST endpoints, you can handle user authentication through GraphQL mutations. This allows you to use the same credentials as your Phoenix application but return a JWT token that can be used for subsequent API requests. The video demonstrates how to implement this while maintaining security best practices.

def login(%{email: email, password: password}, _info) do
  with %User{} = user <- Users.get_user_by_email_and_password(email, password),
       {:ok, jwt, _full_claims} <- Users.Guardian.encode_and_sign(user) do
    {:ok, %{token: jwt}}
  else
    _ -> {:error, "Incorrect email or password"}
  end
end

Secured CRUD Operations with GraphQL

Building on the authentication system, you can create a complete CRUD interface for your resources through GraphQL. This provides a flexible API where clients can specify exactly what fields they need, reducing over-fetching of data. In the video, we'll implement this with proper authorization checks ensuring only authenticated users can modify data.

def create_brewery(args, %{context: %{current_user: _user}}) do
  case Breweries.create_brewery(args) do
    {:ok, %Brewery{} = brewery} -> {:ok, brewery}
    {:error, changeset} -> {:error, inspect(changeset.errors)}
  end
end

What you will learn:

  • How to set up Absinthe and create a GraphQL schema that maps to your Ecto schemas
  • Implementing JWT authentication through GraphQL mutations
  • Building a complete CRUD API with proper authorization checks
  • Using GraphiQL for testing and documenting your API
  • How to organize resolvers and types in a maintainable way
  • Adding proper error handling for validation and authorization