I’m writing an api that needs to be authenticated, but a specific path (the create user path) doesn’t need to be authenticated.
scope "/", AttoLinkWeb do
pipe_through [:api]
post "/", UserController, :create
end
The rest of the end points are placed in another scope macro
scope "/api", AttoLinkWeb do
pipe_through [:api, :auth]
get "/preview", PreviewController, :create
resources "/user", UserController, except: [:new, :edit, :create]
resources "/", ApiController, except: [:new, :edit]
end
The authentication pipeline and api pipeline are as follows
pipeline :api do
plug :accepts, ["json"]
end
pipeline :auth do
plug AttoLink.Auth.Pipeline
end
This is the authentication pipeline.
defmodule AttoLink.Auth.Pipeline do
use Guardian.Plug.Pipeline,
otp_app: :atto_link,
error_handler: AttoLink.Auth.ErrorHandler,
module: AttoLink.Auth.Guardian
plug Guardian.Plug.VerifySession, claims: %{"typ" => "access"}
plug Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"}
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, allow_blank: true
end
As you can see, the api i’m building has two different end points in two different scopes, but everytime i run the user_controller_test it returns message: unauthenticated, which means all my tests aren’t passing.
defmodule AttoLinkWeb.UserControllerTest do
use AttoLinkWeb.ConnCase
alias AttoLink.Accounts
alias AttoLink.Accounts.User
@create_attrs %{
email: "some email",
password: "some password_hash"
}
@update_attrs %{
email: "some updated email",
password: "some updated password_hash"
}
@invalid_attrs %{email: nil, password: nil}
def fixture(:user) do
{:ok, user} = Accounts.create_user(@create_attrs)
user
end
setup %{conn: conn} do
{:ok, conn: put_req_header(conn, "accept", "application/json")}
end
describe "index" do
test "lists all user", %{conn: conn} do
conn = get(conn, Routes.user_path(conn, :index))
assert json_response(conn, 200)["data"] == []
end
end
describe "create user" do
#fails with 401 error when it should succeed
test "renders user when data is valid", %{conn: conn} do
conn = post(conn, Routes.user_path(conn, :create), user: @create_attrs)
assert %{"id" => id} = json_response(conn, 201)["data"]
conn = get(conn, Routes.user_path(conn, :show, id))
assert %{
"id" => id,
"email" => "some email"
} = json_response(conn, 200)["data"]
end
test "renders errors when data is invalid", %{conn: conn} do
#fails with 401 when it should fail with 422
conn = post(conn, Routes.user_path(conn, :create), user: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{}
end
end
describe "update user" do
setup [:create_user, :sign_in_user]
test "renders user when data is valid", %{conn: conn, user: %User{id: id} = user} do
conn = put(conn, Routes.user_path(conn, :update, user), user: @update_attrs)
assert %{"id" => ^id} = json_response(conn, 200)["data"]
conn = get(conn, Routes.user_path(conn, :show, id))
assert %{
"id" => id,
"email" => "some updated email"
} = json_response(conn, 200)["data"]
end
test "renders errors when data is invalid", %{conn: conn, user: user} do
conn = put(conn, Routes.user_path(conn, :update, user), user: @invalid_attrs)
assert json_response(conn, 422)["errors"] != %{}
end
end
describe "delete user" do
setup [:create_user, :sign_in_user]
test "deletes chosen user", %{conn: conn, user: user} do
conn = delete(conn, Routes.user_path(conn, :delete, user))
assert response(conn, 204)
assert_error_sent 404, fn ->
get(conn, Routes.user_path(conn, :show, user))
end
end
end
defp create_user(_) do
user = fixture(:user)
{:ok, user: user}
end
defp sign_in_user(%{conn: conn, user: user}) do
{:ok, token, _claims} = AttoLink.Auth.Guardian.encode_and_sign(user)
conn = conn |> put_req_header("authorization", "bearer: " <> token)
{:ok, user: user, conn: conn}
end
end
I’ve checked just about everything. I’m currently using guardian 2.0.0. If you have any solutions please point me in the right direction.