Ueberauth Guardian - [error] protocol Enumerable not implemented for %AuthMe.UserManager.User

Hi,

Just went through the getting started tutorial of Ueberauth Guardian, https://github.com/ueberauth/guardian/blob/master/guides/tutorial/start-tutorial.md and getting the following error:

[debug] Processing with AuthMeWeb.SessionController.login/2
  Parameters: %{"_csrf_token" => "ED8hNV01HAoVJgUNJgFUCE01d0NPLhVfvMNv9rRLwB2Fyv-cxE8q6Zzo", "_utf8" => "✓", "user" => %{"password" => "[FILTERED]", "username" => "me"}}
  Pipelines: [:browser, :auth]
[debug] QUERY OK source="users" db=0.4ms
SELECT u0."id", u0."email", u0."password", u0."username", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."username" = $1) ["me"]
[info] Sent 500 in 332ms
[error] #PID<0.494.0> running AuthMeWeb.Endpoint (connection #PID<0.486.0>, stream id 4) terminated
Server: localhost:4000 (http)
Request: POST /login
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol Enumerable not implemented for %AuthMe.UserManager.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, email: "me@me.com", id: 1, inserted_at: ~N[2019-07-27 10:02:07], password: "$argon2id$v=19$m=131072,t=8,p=4$/U8dnLAcxhvQWu3uNrQmGw$FBsHeET8o9+ecOrr2s7y+I3JRneZJUP1r5QJg66usKY", updated_at: ~N[2019-07-27 10:02:07], username: "me"}. This protocol is implemented for: Ecto.Adapters.SQL.Stream, Postgrex.Stream, DBConnection.Stream, DBConnection.PrepareStream, HashSet, Range, Map, Function, List, Stream, Date.Range, HashDict, GenEvent.Stream, MapSet, File.Stream, IO.Stream
        (elixir) /private/tmp/elixir-20190202-21222-1ilp2g0/elixir-1.8.1/lib/elixir/lib/enum.ex:1: Enumerable.impl_for!/1
        (elixir) /private/tmp/elixir-20190202-21222-1ilp2g0/elixir-1.8.1/lib/elixir/lib/enum.ex:141: Enumerable.reduce/3
        (elixir) lib/enum.ex:3015: Enum.reverse/1
        (elixir) lib/enum.ex:2647: Enum.to_list/1
        (elixir) lib/map.ex:181: Map.new_from_enum/1
        (guardian) lib/guardian.ex:573: Guardian.encode_and_sign/4
        (guardian) lib/guardian/plug.ex:208: Guardian.Plug.sign_in/5
        (auth_me) lib/auth_me_web/controllers/session_controller.ex:30: AuthMeWeb.SessionController.login_reply/2
        (auth_me) lib/auth_me_web/controllers/session_controller.ex:1: AuthMeWeb.SessionController.action/2
        (auth_me) lib/auth_me_web/controllers/session_controller.ex:1: AuthMeWeb.SessionController.phoenix_controller_pipeline/2
        (phoenix) lib/phoenix/router.ex:288: Phoenix.Router.__call__/2
        (auth_me) lib/auth_me_web/endpoint.ex:1: AuthMeWeb.Endpoint.plug_builder_call/2
        (auth_me) lib/plug/debugger.ex:122: AuthMeWeb.Endpoint."call (overridable 3)"/2
        (auth_me) lib/auth_me_web/endpoint.ex:1: AuthMeWeb.Endpoint.call/2
        (phoenix) lib/phoenix/endpoint/cowboy2_handler.ex:40: Phoenix.Endpoint.Cowboy2Handler.init/2
        (cowboy) /Users/bigbassroller2017/Sites/space-rocket-phx/auth_me/deps/cowboy/src/cowboy_handler.erl:41: :cowboy_handler.execute/2
        (cowboy) /Users/bigbassroller2017/Sites/space-rocket-phx/auth_me/deps/cowboy/src/cowboy_stream_h.erl:296: :cowboy_stream_h.execute/3
        (cowboy) /Users/bigbassroller2017/Sites/space-rocket-phx/auth_me/deps/cowboy/src/cowboy_stream_h.erl:274: :cowboy_stream_h.request_process/3
        (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

lib/auth_me_web/controllers/session_controller.ex

defmodule AuthMeWeb.SessionController do
  use AuthMeWeb, :controller

  alias AuthMe.{UserManager, UserManager.User, UserManager.Guardian}

  def new(conn, _) do
    changeset = UserManager.change_user(%User{})
    maybe_user = Guardian.Plug.current_resource(conn)
    if maybe_user do
      redirect(conn, to: "/secret")
    else
      render(conn, "new.html", changeset: changeset, action: Routes.session_path(conn, :login))
    end
  end

  def login(conn, %{"user" => %{"username" => username, "password" => password}}) do
    UserManager.authenticate_user(username, password)
    |> login_reply(conn)
  end

  def logout(conn, _) do
    conn
    |> Guardian.Plug.sign_out(Guardian, _opts = [])
    |> redirect(to: "/login")
  end

  defp login_reply({:ok, user}, conn) do
    conn
    |> put_flash(:info, "Welcome back!")
    |> Guardian.Plug.sign_in(Guardian, user)
    |> redirect(to: "/protected")
  end

  defp login_reply({:error, reason}, conn) do
    conn
    |> put_flash(:error, to_string(reason))
    |> new(%{})
  end
end

lib/auth_me/user_manager/guardian.ex

defmodule AuthMe.UserManager.Guardian do
  use Guardian, otp_app: :auth_me

  alias AuthMe.UserManager

  def subject_for_token(user, _claims) do
    {:ok, to_string(user.id)}
  end

  def resource_from_claims(%{"sub" => id}) do
    case UserManager.get_user(id) do
      nil -> {:error, :resource_not_found}
      user -> {:ok, user}
    end
  end
end

I am not sure what the issue is. It sounds like the struct is in the wrong format.

I put the code up on a repo along with revised tutorial here: https://github.com/bigbassroller/auth-me

Any help very appreciated!

:wave:

I think the error is the same as in Protocol Enumerable not implemented for error with guardian login

1 Like

Thanks idiot, it was the same issue and solution.