Current section
Files
Jump to
Current section
Files
lib/noa/web/controllers/token/introspect_controller.ex
defmodule Noa.Web.IntrospectController do
@moduledoc false
use Noa.Web, :controller
action_fallback Noa.Web.FallbackController
alias Noa.Tokens.{Scopes}
alias Noa.Web.{TokenUtils}
def introspect(conn, %{} = attrs) do
noa_ctxt = Map.get(conn.assigns, :noa_ctxt)
stub = Map.get(attrs, "token", "")
token_type = Map.get(attrs, "token_type_hint", "access_token")
with {:ok, token} <- TokenUtils.get_validated_token(stub, token_type),
:ok <- TokenUtils.check_validity_period(token),
:ok <- TokenUtils.check_revocation_status(token),
:ok <- check_mismatched_token(token, noa_ctxt)
do
resp = introspect_resp(token, compute_scope(token.scope, noa_ctxt))
conn |> put_status(200) |> json(resp)
else
_e -> conn |> put_status(200) |> json(%{"active" => false})
end
rescue
e -> {:error, :server_error, "#{inspect e}"}
end
defp check_mismatched_token(%{provider_id: id}, %{provider: %{id: id}}), do: :ok
defp check_mismatched_token(_, _), do: {:error, :invalid_token, "mismatch"}
defp compute_scope(token_scope, %{provider: prov, resource: res}) when res != nil do
token_scope
|> String.split()
|> MapSet.new()
|> MapSet.intersection(Scopes.get(prov, [res]))
end
defp compute_scope(token_scope, %{provider: prov, client: client}) when client != nil do
token_scope
|> String.split()
|> MapSet.new()
|> MapSet.intersection(Scopes.get_all(prov))
end
defp compute_scope(_, _), do: MapSet.new()
defp introspect_resp(token, computed_scope) do
if MapSet.size(computed_scope) == 0 do
%{active: false}
else
iat = DateTime.to_unix(token.issued_on)
exp = DateTime.to_unix(token.expires_on)
%{
active: true, scope: token.scope, client_id: token.issued_to,
iat: iat, nbf: iat, exp: exp,
}
end
end
end