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.
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
Thanks!
Ah ya! That’s nice. I assume you have used Guardian.Plug.LoadResource in the router pipeline right? Much cleaner. Thanks for sharing!
Cool, thanks again for sharing. I updated the post!
This is great. Looking forward to seeing more!
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
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! 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}})
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
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.
Yes I did, that was exactly the problem, stupid me , thank you.
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
https://devchat.tv/js-jabber/jsj-246-graphql-and-apollo-with-uri-goldshtein