Screencast
25. GraphQL with Phoenix and Absinthe
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