I'm using Guardian and trying to use Canary however, I can't seem to fetch the current user, canary needs the current_user in conn.assigns, I've followed this, if I ask for (inside a controller action):
Guardian.Plug.authenticated?(conn)
I get true, but if I do:
Guardian.Plug.current_resource(conn)
It's just blank.
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 in 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 create 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'm just missing something.
While not ideal, this was my solution, this question does not accept more answers since it is way too old to even validate that the answers work:
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