Packages
indieweb
0.0.14
0.0.66
0.0.65
0.0.64
0.0.63
0.0.62
0.0.61
0.0.60
0.0.59
0.0.58
0.0.56
0.0.55
0.0.54
0.0.53
0.0.51
0.0.50
0.0.49
0.0.48
0.0.47
0.0.46
0.0.42
0.0.41
0.0.40
0.0.39
0.0.38
0.0.37
0.0.36
0.0.35
0.0.34
0.0.33
0.0.32
0.0.31
0.0.30
0.0.29
0.0.28
0.0.27
0.0.26
0.0.25
0.0.24
0.0.23
0.0.22
0.0.21
0.0.20
0.0.19
0.0.17
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.3
0.0.2
0.0.1
Collection of common IndieWeb utilites like authorship resolution, Webmention, post type discovery and IndieAuth.
Current section
Files
Jump to
Current section
Files
lib/indieweb/auth.ex
defmodule IndieWeb.Auth do
@moduledoc """
Provides logic for handling [IndieAuth](https://indieauth.spec.indieweb.org) interactions.
"""
@doc "Provides the adapter to be used by `IndieWeb.Auth` for stateful actions."
@spec adapter() :: IndieWeb.Auth.Adapter.t()
def adapter(),
do:
Application.get_env(
:indieweb,
:auth_adapter,
IndieWeb.Auth.Adapters.Default
)
@doc "Provides endpoint information for well known endpoints in IndieAuth."
@spec endpoint_for(atom(), binary()) :: binary() | nil
def endpoint_for(type, uri)
def endpoint_for(component, url) when component in ~w(authorization token)a do
IndieWeb.LinkRel.find(url, "#{component}_endpoint") |> List.first()
end
def endpoint_for(:redirect_uri, url),
do: IndieWeb.LinkRel.find(url, "redirect_uri")
def endpoint_for(_, _), do: nil
@spec authenticate(map()) :: {:ok, any()} | {:error, any()}
def authenticate(params)
def authenticate(%{"response_type" => "id"} = params) do
case do_validate_request(params, ~w(client_id redirect_uri state me)) do
{:error, _} = error ->
error
{:ok,
%{
"client_id" => client_id,
"redirect_uri" => redirect_uri,
"state" => state
}} ->
code = IndieWeb.Auth.Code.generate(client_id, redirect_uri)
do_generate_redirect_uri(redirect_uri, code, state)
end
end
def authenticate(%{"response_type" => "code"} = params) do
case do_validate_request(params, ~w(client_id redirect_uri state me)) do
{:error, _} = error ->
error
{:ok,
%{
"client_id" => client_id,
"redirect_uri" => redirect_uri,
"state" => state
} = args} ->
scope = Map.get(args, "scope", "read")
code =
IndieWeb.Auth.Code.generate(client_id, redirect_uri, %{
"scope" => scope
})
do_generate_redirect_uri(redirect_uri, code, state)
end
end
def authenticate(_), do: {:error, :unrecognized_authorization_request}
defp do_generate_redirect_uri(redirect_uri, code, state) do
query =
redirect_uri
|> URI.parse()
|> Map.get(:query)
|> (&(URI.decode_query(&1 || "", %{"code" => code, "state" => state})
|> URI.encode_query())).()
redirect_uri
|> URI.parse()
|> Map.put(:query, query)
|> URI.to_string()
end
defp do_validate_request(params, expected_keys) do
proper_args = Map.take(params, expected_keys)
missing_keys = expected_keys -- Map.keys(params)
cond do
!Enum.empty?(missing_keys) ->
{:error, :missing_required_keys, keys: missing_keys}
!adapter().valid_user?(params["me"]) ->
{:error, :invalid_user}
true ->
{:ok, proper_args}
end
end
end