defmodule Rivet.Auth.Access do
@moduledoc """
Validation of tokens for accessing site (after refresh)
Note: this is the start of the next iteration, and it will replace
Rivet.Auth.Token
"""
alias Rivet.Auth
alias Rivet.Ident
@doc """
iex> alias Rivet.Auth
iex> check([""], %Auth.Domain{})
{:missing, %Auth.Domain{log: "Missing authorization header value"}}
iex> check([], %Auth.Domain{})
{:missing, %Auth.Domain{log: "Missing authorization header value"}}
iex> check(["bearer token"], %Auth.Domain{})
{:error, %Auth.Domain{log: "Invalid authorization"}}
iex> check(["narf"], %Auth.Domain{})
{:error, %Auth.Domain{log: "Authorization header exists but is not formatted properly"}}
iex> check(["narf narf"], %Auth.Domain{})
{:error, %Auth.Domain{log: "Invalid authorization type: narf"}}
"""
@spec check(auth_header :: list(String.t()), Auth.Domain.t()) ::
{:ok | :missing | :error, Auth.Domain.t()}
# | def(check([], %Auth.Domain{} = auth),
# do: {:missing, %Auth.Domain{auth | log: "Missing authorization header"}}
# )
def check([""], %Auth.Domain{} = auth),
do: {:missing, %Auth.Domain{auth | log: "Missing authorization header value"}}
def check([header], %Auth.Domain{} = auth) do
with [type, tok] <- String.split(header, " ", parts: 2) do
case String.downcase(type) do
"bearer" -> {:bearer, tok}
_ -> {:error, %Auth.Domain{auth | log: "Invalid authorization type: #{type}"}}
end
else
_ ->
{:error,
%Auth.Domain{auth | log: "Authorization header exists but is not formatted properly"}}
end
|> process_authorization(auth)
end
def check(_, %Auth.Domain{} = auth),
do: {:missing, %Auth.Domain{auth | log: "Missing authorization header value"}}
# Standard bearer tokens for users
defp process_authorization({:bearer, token}, auth) do
case Auth.Token.Verify.jwt(token, :acc) do
{:error, reason} ->
{:error, %Auth.Domain{auth | log: reason}}
{:ok, claims} ->
auth = %Auth.Domain{auth | status: :authed, token: %{ref: token, claims: claims}}
# this checks the validation token embedded within the refresh token
case Auth.Token.Check.jwt(auth) |> Ident.User.Lib.check_user_status() do
{:ok, %Auth.Domain{} = auth} -> {:ok, auth}
# we passed signature, but the claims weren't right
{:error, %Auth.Domain{} = auth} -> {:error, %Auth.Domain{auth | status: :unknown}}
end
end
end
defp process_authorization(pass, _), do: pass
end