Packages
oidcc
3.1.0-beta.1
3.7.2
3.7.1
3.7.0
3.6.0
3.5.2
3.5.1
3.5.0
retired
3.4.0
3.3.0
3.2.6
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.2.0-beta.3
3.2.0-beta.2
retired
3.2.0-beta.1
retired
3.1.2
3.1.2-beta.1
retired
3.1.1
retired
3.1.0
retired
3.1.0-beta.2
retired
3.1.0-beta.1
retired
3.0.2
3.0.1
retired
3.0.0
retired
3.0.0-rc.6
retired
3.0.0-rc.5
retired
3.0.0-rc.4
retired
3.0.0-rc.3
retired
3.0.0-rc.2
retired
3.0.0-rc.1
retired
3.0.0-alpha.5
retired
3.0.0-alpha.4
retired
3.0.0-alpha.3
retired
3.0.0-alpha.2
retired
3.0.0-alpha.1
retired
2.0.0-alpha.2
retired
2.0.0-alpha.1
retired
1.8.1
retired
1.8.0
retired
1.7.0
retired
1.6.0
retired
1.5.1
retired
1.5.0
retired
1.4.0
retired
1.3.0
retired
1.2.1
retired
1.2.0
retired
1.1.0
retired
1.0.1
retired
1.0.0
retired
OpenID Connect client library for the BEAM.
Retired package: Security issue - DoS Vulnerability, see https://github.com/erlef/oidcc/security/advisories/GHSA-mj35-2rgf-cv8p
Current section
Files
Jump to
Current section
Files
src/oidcc_decode_util.erl
%%%-------------------------------------------------------------------
%% @doc Response Decoding Utils
%% @end
%% @since 3.0.0
%%%-------------------------------------------------------------------
-module(oidcc_decode_util).
-export([extract/3]).
-export([parse_setting_binary/2]).
-export([parse_setting_binary_list/2]).
-export([parse_setting_boolean/2]).
-export([parse_setting_list_enum/3]).
-export([parse_setting_number/2]).
-export([parse_setting_uri/2]).
-export([parse_setting_uri_https/2]).
-export_type([error/0]).
-type error() ::
{missing_config_property, Key :: atom()}
| {invalid_config_property, {
Type ::
uri
| uri_https
| binary
| number
| list_of_binaries
| boolean
| scopes_including_openid
| enum
| alg_no_none,
Field :: atom()
}}.
%% @private
-spec extract(
Map :: #{binary() => term()},
Keys :: [{required, Key, ParseFn} | {optional, Key, Default, ParseFn}],
Acc :: #{atom() => term()}
) ->
{ok, {Matched, Rest}} | {error, error()}
when
Key :: atom(),
Default :: term(),
ParseFn :: fun((Setting :: term(), Key) -> {ok, term()} | {error, error()}),
Matched :: #{Key => Default | undefined | term()},
Rest :: #{binary() => term()}.
extract(Map1, [{required, Key, ParseFn} | RestKeys], Acc) ->
case maps:take(atom_to_binary(Key), Map1) of
{Value, Map2} ->
case ParseFn(Value, Key) of
{ok, Parsed} ->
extract(Map2, RestKeys, maps:put(Key, Parsed, Acc));
{error, Reason} ->
{error, Reason}
end;
error ->
{error, {missing_config_property, Key}}
end;
extract(Map1, [{optional, Key, Default, ParseFn} | RestKeys], Acc) ->
case maps:take(atom_to_binary(Key), Map1) of
{Value, Map2} ->
case ParseFn(Value, Key) of
{ok, Parsed} ->
extract(Map2, RestKeys, maps:put(Key, Parsed, Acc));
{error, Reason} ->
{error, Reason}
end;
error ->
extract(Map1, RestKeys, maps:put(Key, Default, Acc))
end;
extract(Map, [], Acc) ->
{ok, {Acc, Map}}.
%% @private
-spec parse_setting_uri(Setting :: term(), Field :: atom()) ->
{ok, uri_string:uri_string()} | {error, error()}.
parse_setting_uri(Setting, _Field) when is_binary(Setting) ->
{ok, Setting};
parse_setting_uri(_Setting, Field) ->
{error, {invalid_config_property, {uri, Field}}}.
%% @private
-spec parse_setting_uri_https(Setting :: term(), Field :: atom()) ->
{ok, uri_string:uri_string()} | {error, error()}.
parse_setting_uri_https(Setting, Field) when is_binary(Setting) ->
case uri_string:parse(Setting) of
#{scheme := <<"https">>} ->
{ok, Setting};
#{scheme := _Scheme} ->
{error, {invalid_config_property, {uri_https, Field}}}
end;
parse_setting_uri_https(_Setting, Field) ->
{error, {invalid_config_property, {uri_https, Field}}}.
%% @private
-spec parse_setting_binary(Setting :: term(), Field :: atom()) ->
{ok, binary()} | {error, error()}.
parse_setting_binary(Setting, _Field) when is_binary(Setting) ->
{ok, Setting};
parse_setting_binary(_Setting, Field) ->
{error, {invalid_config_property, {binary, Field}}}.
%% @private
-spec parse_setting_binary_list(Setting :: term(), Field :: atom()) ->
{ok, [binary()]} | {error, error()}.
parse_setting_binary_list(Setting, Field) when is_list(Setting) ->
case lists:all(fun is_binary/1, Setting) of
true ->
{ok, Setting};
false ->
{error, {invalid_config_property, {list_of_binaries, Field}}}
end;
parse_setting_binary_list(_Setting, Field) ->
{error, {invalid_config_property, {list_of_binaries, Field}}}.
%% @private
-spec parse_setting_number(Setting :: term(), Field :: atom()) ->
{ok, integer()} | {error, error()}.
parse_setting_number(Setting, _Field) when is_integer(Setting) ->
{ok, Setting};
parse_setting_number(_Setting, Field) ->
{error, {invalid_config_property, {number, Field}}}.
%% @private
-spec parse_setting_boolean(Setting :: term(), Field :: atom()) ->
{ok, boolean()} | {error, error()}.
parse_setting_boolean(Setting, _Field) when is_boolean(Setting) ->
{ok, Setting};
parse_setting_boolean(_Setting, Field) ->
{error, {invalid_config_property, {boolean, Field}}}.
%% @private
-spec parse_setting_list_enum(
Setting :: term(),
Field :: atom(),
Parse :: fun((binary()) -> {ok, Value} | error)
) ->
{ok, [Value]} | {error, error()}
when
Value :: term().
parse_setting_list_enum(Setting, Field, Parse) ->
case parse_setting_binary_list(Setting, Field) of
{ok, Values} ->
Parsed =
lists:map(
fun(Value) ->
case Parse(Value) of
{ok, ParsedValue} ->
{ok, ParsedValue};
error ->
{error, Value}
end
end,
Values
),
case
lists:filter(
fun
({ok, _Value}) ->
false;
({error, _Value}) ->
true
end,
Parsed
)
of
[] ->
{ok, lists:map(fun({ok, Value}) -> Value end, Parsed)};
[{error, _InvalidValue} | _Rest] ->
{error, {invalid_config_property, {enum, Field}}}
end;
{error, Reason} ->
{error, Reason}
end.