Phoenix GraphQL Tutorial with Absinthe: Authentication with Guardian

This is the third post in a series on building a GraphQL API in Phoenix with Absinthe. In this post I cover authentication with Guardian.


Awesome stuff man.

1 Like

Great article Ryan!

What do you think of this code? It’s similar to yours but I pattern match on a valid changeset in the function instead of doing a extra case inside the function.

Also since you are using Guardian you can build your context.ex like this

1 Like


Ah ya! That’s nice. I assume you have used Guardian.Plug.LoadResource in the router pipeline right? Much cleaner. Thanks for sharing!

1 Like

Yes you are right

Cool, thanks again for sharing. I updated the post!

This is great. Looking forward to seeing more! :+1:

1 Like

Ryan, thanks a lot for these three awesome posts. I’ve enjoyed them a lot and definitely posts like yours are very valuable for the Elixir community :ok_hand:

In this last one i’ve been able to catch a couple of typos (what an honour!!): in mix.exs and web/plugs/context.ex you use PhoenixGraphQL instead of MyApp as you do everywhere else.

Have an amazing 2017, you deserve it!!


Thanks for catching those! :grinning: I’ll get them fixed.

I hope you have a wonderful 2017 too!


I can’t get the authorization to work, I get a token successfully:

But when I do a query with the token it returns unauthorized

I have no idea what is going on, and my files seem to be the same as yours (with some caveats, like encrypted_password instead of password_hash)

Here is the plug

defmodule Vulkan.Web.Context do
  @behaviour Plug
  import Plug.Conn
  def init(opts), do: opts
  def call(conn, _) do
    case Guardian.Plug.current_resource(conn) do
      nil -> conn
      user ->
        put_private(conn, :absinthe, %{context: %{current_user: user}})

The router

defmodule Vulkan.Router do
  use Vulkan.Web, :router

  pipeline :api do
    plug :accepts, ["json"]
  pipeline :graphql do
    plug Guardian.Plug.VerifyHeader, realm: "Bearer"
    plug Guardian.Plug.LoadResource
    plug Vulkan.Web.Context

  scope "/api" do
    pipe_through :graphql
    forward "/", Absinthe.Plug,
      schema: Vulkan.Schema

  forward "/graphiql", Absinthe.Plug.GraphiQL,
    schema: Vulkan.Schema


The post resolver

defmodule Vulkan.PostResolver do
  alias Vulkan.{ Repo, Post }
  import Ecto.Query, only: [where: 2]
  def all(_args, %{context: %{current_user: %{id: id}}}) do
    posts =
      |> where(user_id: ^id)
      |> Repo.all
    {:ok, posts}
  def all(_args, _info) do
    {:error, "Unauthorized"}

The session model

defmodule Vulkan.Session do
  alias Vulkan.User
  def authenticate(params, repo) do
    user = repo.get_by(User, email: String.downcase(
    case check_password(user, params.password) do
      true -> {:ok, user}
      _ -> {:error, "Incorrect login credentials"}
  defp check_password(user, password) do
    case user do
      nil -> false
      _ -> Comeonin.Bcrypt.checkpw(password, user.encrypted_password)

I have no idea of why it doesn’t work, being the same codebase it should, any ideas?

EDIT I’m pretty dumb, was doing requests to /graphql instead of /api :laughing:

1 Like

Sorry to just get to this. It looks like you figured out the issue (sending requests to wrong route). Is that right? Happy to help if you are still having trouble.

1 Like

Yes I did, that was exactly the problem, stupid me :smile:, thank you.

1 Like

Sorry if not related to topic.
It seems that meteor js team is also moving to Graph QL.
Worth consider listen what they are doing :slight_smile:

1 Like