Packages
The shared sans-io core of the gleam-atproto client packages: XRPC error vocabulary and response handling, plus the OAuth effect kernel.
Current section
Files
Jump to
Current section
Files
src/atproto_core@oauth@flow.erl
-module(atproto_core@oauth@flow).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/atproto_core/oauth/flow.gleam").
-export([start/8]).
-export_type([start_error/0, authorized/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Start an authorization flow as an `Effect`: resolve the PDS, discover\n"
" the authorization server, and push the request (PAR) with PKCE + DPoP.\n"
" One-shot inputs (PKCE challenge, `state`) come in as parameters.\n"
).
-type start_error() :: {resolve_failed, binary()} |
{discover_failed, binary()} |
{par_failed, binary()}.
-type authorized() :: {authorized, binary(), binary(), binary(), binary()}.
-file("src/atproto_core/oauth/flow.gleam", 84).
-spec push_par(
atproto_core@oauth@metadata:auth_server_metadata(),
list({binary(), binary()})
) -> atproto_core@oauth@effect:effect({ok, binary()} | {error, start_error()}).
push_par(Server_metadata, Form) ->
atproto_core@oauth@effect:'try'(
begin
_pipe = atproto_core@oauth@transport:post_form_with_dpop(
erlang:element(5, Server_metadata),
Form
),
atproto_core@oauth@effect:map_error(
_pipe,
fun(Field@0) -> {par_failed, Field@0} end
)
end,
fun(Resp) ->
atproto_core@oauth@effect:done(
case (erlang:element(2, Resp) >= 200) andalso (erlang:element(
2,
Resp
)
< 300) of
true ->
_pipe@1 = atproto_core@xrpc:parse(
erlang:element(4, Resp),
gleam@dynamic@decode:at(
[<<"request_uri"/utf8>>],
{decoder,
fun gleam@dynamic@decode:decode_string/1}
)
),
gleam@result:map_error(
_pipe@1,
fun(E) -> {par_failed, gleam@string:inspect(E)} end
);
false ->
{error,
{par_failed,
<<<<<<"PAR "/utf8,
(erlang:integer_to_binary(
erlang:element(2, Resp)
))/binary>>/binary,
": "/utf8>>/binary,
(erlang:element(4, Resp))/binary>>}}
end
)
end
).
-file("src/atproto_core/oauth/flow.gleam", 34).
-spec start(
binary(),
binary(),
binary(),
binary(),
binary(),
binary(),
binary(),
list({binary(), binary()})
) -> atproto_core@oauth@effect:effect({ok, authorized()} |
{error, start_error()}).
start(
Resolver,
Identifier,
Client_id,
Redirect_uri,
Scope,
Pkce_challenge,
State,
Extra_form
) ->
atproto_core@oauth@effect:'try'(
begin
_pipe = atproto_core@identity:resolve_mini_doc(Resolver, Identifier),
atproto_core@oauth@effect:map_error(
_pipe,
fun(E) -> {resolve_failed, gleam@string:inspect(E)} end
)
end,
fun(Doc) ->
atproto_core@oauth@effect:'try'(
begin
_pipe@1 = atproto_core@oauth@metadata:discover(
erlang:element(3, Doc)
),
atproto_core@oauth@effect:map_error(
_pipe@1,
fun(E@1) ->
{discover_failed, gleam@string:inspect(E@1)}
end
)
end,
fun(Server_metadata) ->
Form = lists:append(
[{<<"client_id"/utf8>>, Client_id},
{<<"response_type"/utf8>>, <<"code"/utf8>>},
{<<"code_challenge"/utf8>>, Pkce_challenge},
{<<"code_challenge_method"/utf8>>, <<"S256"/utf8>>},
{<<"redirect_uri"/utf8>>, Redirect_uri},
{<<"scope"/utf8>>, Scope},
{<<"state"/utf8>>, State},
{<<"login_hint"/utf8>>, Identifier}],
Extra_form
),
atproto_core@oauth@effect:'try'(
push_par(Server_metadata, Form),
fun(Request_uri) ->
Redirect_url = <<<<(erlang:element(
3,
Server_metadata
))/binary,
"?"/utf8>>/binary,
(gleam@uri:query_to_string(
[{<<"client_id"/utf8>>, Client_id},
{<<"request_uri"/utf8>>, Request_uri}]
))/binary>>,
atproto_core@oauth@effect:done(
{ok,
{authorized,
Redirect_url,
erlang:element(3, Doc),
erlang:element(2, Server_metadata),
erlang:element(4, Server_metadata)}}
)
end
)
end
)
end
).