diff --git a/examples/gatekeeper-auth/README.md b/examples/gatekeeper-auth/README.md index 5419ec1fd1..789560cc3f 100644 --- a/examples/gatekeeper-auth/README.md +++ b/examples/gatekeeper-auth/README.md @@ -122,7 +122,7 @@ First let's make a `GET` request to the proxy endpoint *without* the auth token. ```console $ curl -sv "http://localhost:4000/proxy/v1/shape?table=items&offset=-1" ... -< HTTP/1.1 403 Forbidden +< HTTP/1.1 401 Unauthorized ... ``` diff --git a/examples/gatekeeper-auth/api/lib/api/token.ex b/examples/gatekeeper-auth/api/lib/api/token.ex index 723a2471c0..c0d636f56a 100644 --- a/examples/gatekeeper-auth/api/lib/api/token.ex +++ b/examples/gatekeeper-auth/api/lib/api/token.ex @@ -22,9 +22,26 @@ defmodule Api.Token do end def verify(%ShapeDefinition{} = request_shape, token) do - with {:ok, %{"shape" => token_params}} <- JWT.verify_and_validate(token, JWT.signer()), - {:ok, token_shape} <- Shape.from(token_params) do + with {:ok, shape_claim} <- validate(token) do + matches(request_shape, shape_claim) + end + end + + defp validate(token) do + with {:ok, %{"shape" => shape_claim}} <- JWT.verify_and_validate(token, JWT.signer()) do + {:ok, shape_claim} + else + _alt -> + {:error, :invalid} + end + end + + defp matches(%ShapeDefinition{} = request_shape, %{} = shape_claim) do + with {:ok, token_shape} <- Shape.from(shape_claim) do Shape.matches(request_shape, token_shape) + else + _alt -> + false end end end diff --git a/examples/gatekeeper-auth/api/lib/api_web/authenticator.ex b/examples/gatekeeper-auth/api/lib/api_web/authenticator.ex index 907b8069f4..a0dacc1ecd 100644 --- a/examples/gatekeeper-auth/api/lib/api_web/authenticator.ex +++ b/examples/gatekeeper-auth/api/lib/api_web/authenticator.ex @@ -17,12 +17,15 @@ defmodule ApiWeb.Authenticator do request end - def authorise(shape, request_header_list) do - header_map = Enum.into(request_header_list, %{}) + def authorise(shape, request_headers) do + header_map = Enum.into(request_headers, %{}) header_key = String.downcase(@header_name) with {:ok, "Bearer " <> token} <- Map.fetch(header_map, header_key) do Token.verify(shape, token) + else + _alt -> + {:error, :missing} end end diff --git a/examples/gatekeeper-auth/api/lib/api_web/plugs/auth/verify_token.ex b/examples/gatekeeper-auth/api/lib/api_web/plugs/auth/verify_token.ex index 8544d3bedf..2760efc005 100644 --- a/examples/gatekeeper-auth/api/lib/api_web/plugs/auth/verify_token.ex +++ b/examples/gatekeeper-auth/api/lib/api_web/plugs/auth/verify_token.ex @@ -16,13 +16,18 @@ defmodule ApiWeb.Plugs.Auth.VerifyToken do def call(%{assigns: %{shape: shape}, req_headers: headers} = conn, _opts) do case Authenticator.authorise(shape, headers) do - true -> + {:error, message} when message in [:invalid, :missing] -> conn + |> send_resp(401, "Unauthorized") + |> halt() - _alt -> + false -> conn |> send_resp(403, "Forbidden") |> halt() + + true -> + conn end end end diff --git a/examples/gatekeeper-auth/api/test/api_web/controllers/proxy_controller_test.exs b/examples/gatekeeper-auth/api/test/api_web/controllers/proxy_controller_test.exs index f1f6a5696a..6bc2190f56 100644 --- a/examples/gatekeeper-auth/api/test/api_web/controllers/proxy_controller_test.exs +++ b/examples/gatekeeper-auth/api/test/api_web/controllers/proxy_controller_test.exs @@ -18,14 +18,14 @@ defmodule ApiWeb.ProxyControllerTest do test "requires auth", %{conn: conn} do assert conn |> get("/proxy/v1/shape", table: "items") - |> response(403) + |> response(401) end test "requires valid auth header", %{conn: conn} do assert conn |> put_req_header("authorization", "Bearer invalid-token") |> get("/proxy/v1/shape", table: "items") - |> response(403) + |> response(401) end test "requires matching shape definition", %{conn: conn} do