I use Guardian and try to use Canary however I cannot find the current user, the canary needs current_user in conn.assigns, I followed this if I ask (inside the controller action):
Guardian.Plug.authenticated?(conn)
I believe, but if I do this:
Guardian.Plug.current_resource(conn)
It is just empty.
I have this code in my api pipeline:
pipeline :private_api do plug :accepts, ["json"] plug Guardian.Plug.LoadResource plug Guardian.Plug.VerifyHeader plug Guardian.Plug.EnsureAuthenticated, handler: SessionController plug MyApp.Plug.CurrentUser end
and for MyApp.Plug.CurrentUser
defmodule MyApp.Plug.CurrentUser do def init(opts), do: opts def call(conn, _opts) do current_user = Guardian.Plug.current_resource(conn) Plug.Conn.assign(conn, :current_user, current_user) end end
Session Creation Method:
def create(conn, %{"session" => session_params}) do case MyApp.Session.authenticate(session_params) do {:ok, user} -> {:ok, jwt, _full_claims} = user |> Guardian.encode_and_sign(:token) Plug.Conn.assign(conn, :current_user, user) conn |> put_status(:created) |> render("show.json", jwt: jwt, user: user) :error -> conn |> put_status(:unprocessable_entity) |> render("error.json") end end
Maybe I just missed something.
Edit:
I worked by changing MyApp.Plug.CurrentUser as follows:
defmodule MyApp.Plug.CurrentUser do alias MyApp.GuardianSerializer def init(opts), do: opts def call(conn, _opts) do current_token = Guardian.Plug.current_token(conn) case Guardian.decode_and_verify(current_token) do {:ok, claims} -> case GuardianSerializer.from_token(claims["sub"]) do {:ok, user} -> Plug.Conn.assign(conn, :current_user, user) {:error, _reason} -> conn end {:error, _reason} -> conn end end end
Although this works, maybe there is a better way or another way how to use sign_in.