Implement token verification and revocation
This commit is contained in:
parent
9a6b7eb518
commit
9657ab818c
|
@ -47,17 +47,33 @@ defmodule HostasWeb.Auth.TokenController do
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Responds with 200 OK if the requester's `Bearing` header
|
Responds with 200 OK if the requester's `Bearing` header
|
||||||
contains a valid, non-expired API token
|
contains a valid, non-expired API token, along with a
|
||||||
|
payload with an `expires` key detailing when the key
|
||||||
|
expires.
|
||||||
"""
|
"""
|
||||||
def verify(_conn, _params) do
|
def verify(conn, _params) do
|
||||||
:ok
|
conn
|
||||||
|
|> put_status(200)
|
||||||
|
|> json(%{"expires" => conn.assigns[:token].expires})
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Deletes the token the requester used in the `Bearing` header
|
Deletes the token the requester used in the `Bearing` header
|
||||||
"""
|
"""
|
||||||
def revoke(_conn, _params) do
|
def revoke(conn, %{"id" => id_param}) do
|
||||||
:ok
|
with {:parsed_id, {id, ""}} <- {:parsed_id, Integer.parse(id_param, 10)},
|
||||||
|
{:ok, token} <- fetch_token(id, conn),
|
||||||
|
{:can_access, true} <- {:can_access, token.denizen_id == conn.assigns[:denizen].id} do
|
||||||
|
Repo.delete_all(from t in Token, where: t.id == ^token.id)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> send_resp(200, "")
|
||||||
|
else
|
||||||
|
_ ->
|
||||||
|
conn
|
||||||
|
|> put_status(404)
|
||||||
|
|> json(%{"error" => "Token not found"})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -67,4 +83,15 @@ defmodule HostasWeb.Auth.TokenController do
|
||||||
def renew(_conn, _params) do
|
def renew(_conn, _params) do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp fetch_token(id, conn) do
|
||||||
|
if id == conn.assigns[:token].id do
|
||||||
|
{:ok, conn.assigns[:token]}
|
||||||
|
else
|
||||||
|
case Repo.one(from t in Token, where: t.id == ^id) do
|
||||||
|
nil -> {:error, :token_not_found}
|
||||||
|
token -> {:ok, token}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,7 +32,7 @@ defmodule HostasWeb.Auth.TokenControllerTest do
|
||||||
|
|
||||||
test "fails due to non-existant denizen", %{conn: conn} do
|
test "fails due to non-existant denizen", %{conn: conn} do
|
||||||
conn = post(conn, ~p"/hostapi/auth/token", %{handle: "denizen", password: "password"})
|
conn = post(conn, ~p"/hostapi/auth/token", %{handle: "denizen", password: "password"})
|
||||||
assert json_response(conn, 404)["error"] == "No user with handle testuser"
|
assert json_response(conn, 404)["error"] == "No user with handle denizen"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails due to missing fields", %{conn: conn} do
|
test "fails due to missing fields", %{conn: conn} do
|
||||||
|
@ -70,7 +70,7 @@ defmodule HostasWeb.Auth.TokenControllerTest do
|
||||||
|> put_req_header("authorization", "Bearer unknown_credential")
|
|> put_req_header("authorization", "Bearer unknown_credential")
|
||||||
|> get(~p"/hostapi/auth/token")
|
|> get(~p"/hostapi/auth/token")
|
||||||
|
|
||||||
assert json_response(conn, 200)["error"] == "Token expired"
|
assert json_response(conn, 401)["error"] == "API key not found"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ defmodule HostasWeb.Auth.TokenControllerTest do
|
||||||
|> put_req_header("authorization", "Bearer #{struct.token}")
|
|> put_req_header("authorization", "Bearer #{struct.token}")
|
||||||
|> delete(~p"/hostapi/auth/token/#{struct.id}")
|
|> delete(~p"/hostapi/auth/token/#{struct.id}")
|
||||||
|
|
||||||
assert json_response(conn, 200)
|
assert response(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fails because it's someone else's token", %{conn: conn} do
|
test "fails because it's someone else's token", %{conn: conn} do
|
||||||
|
|
Loading…
Reference in New Issue