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.

https://ryanswapp.com/2016/12/06/phoenix-graphql-tutorial-with-absinthe-authentication-with-guardian/

14 Likes

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.

https://gist.github.com/hl/2ff2e3e8ef71bb8b45e8fa52eabbcb53#file-user-ex-L30-L31

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

https://gist.github.com/hl/6372b3e376ff6a25fa80d39db73e6ab4

1 Like

Thanks!

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

https://gist.github.com/hl/4a5bea125f3394a403f3caa92332cb66

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!!

4 Likes

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

I hope you have a wonderful 2017 too!

4 Likes

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}})
    end
  end
end

The router

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

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

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

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

end

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 =
      Post
      |> where(user_id: ^id)
      |> Repo.all
   
    {:ok, posts}
  end
  
  def all(_args, _info) do
    {:error, "Unauthorized"}
  end
end

The session model

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

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:
https://devchat.tv/js-jabber/jsj-246-graphql-and-apollo-with-uri-goldshtein

1 Like