Packages
oidcc
1.0.0
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: Deprecated - Unmaintained major version, update
Current section
Files
Jump to
Current section
Files
src/oidcc_openid_provider_mgr.erl
-module(oidcc_openid_provider_mgr).
-behaviour(gen_server).
%% API.
-export([start_link/0]).
-export([stop/0]).
-export([add_openid_provider/1]).
-export([get_openid_provider/1]).
-export([find_openid_provider/1]).
-export([get_openid_provider_list/0]).
%% gen_server.
-export([init/1]).
-export([handle_call/3]).
-export([handle_cast/2]).
-export([handle_info/2]).
-export([terminate/2]).
-export([code_change/3]).
-record(state, {
provider = []
}).
%% API.
-spec start_link() -> {ok, pid()}.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
stop() ->
gen_server:cast(?MODULE, stop).
-spec add_openid_provider(Config::map()) ->
{ok, Id::binary(), pid()} | {error, Reason::atom()}.
add_openid_provider(Config) ->
Id = maps:get(id, Config, undefined),
gen_server:call(?MODULE, {add_provider, Id, Config}).
get_openid_provider(Id) ->
gen_server:call(?MODULE, {get_provider, Id}).
get_openid_provider_list() ->
gen_server:call(?MODULE, get_provider_list).
-spec find_openid_provider(Issuer::binary()) -> {ok, pid()}
| {error, not_found}.
find_openid_provider(Issuer) ->
gen_server:call(?MODULE, {find_provider, Issuer}).
%% gen_server.
init([]) ->
{ok, #state{}}.
handle_call({add_provider, undefined, Config}, _From, State) ->
add_provider(Config, State);
handle_call({add_provider, Id, Config}, _From, State) ->
try_adding_provider(Id, Config, State);
handle_call({get_provider, Id}, _From, State) ->
get_provider(Id, State);
handle_call(get_provider_list, _From, State) ->
get_provider_list(State);
handle_call({find_provider, Issuer}, _From, State) ->
find_provider(Issuer, State);
handle_call(_Request, _From, State) ->
{reply, ignored, State}.
handle_cast(stop, State) ->
{stop, normal, State};
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info({'DOWN', MRef, process, _Object, _Info},
#state{provider=Provider} = State) ->
NewProvider = lists:keydelete(MRef, 3, Provider),
{noreply, State#state{provider = NewProvider}};
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
try_adding_provider(Id, Config, State) ->
case is_unique_id(Id, State) of
true -> add_provider(Id, Config, State);
false -> {reply, {error, id_already_used}, State}
end.
add_provider(Config, State) ->
Id = get_unique_id(State),
add_provider(Id, Config, State).
add_provider(Id, Config, State) ->
{ok, Pid} = start_provider(Id, Config),
NewState = insert_provider(Id, Pid, State),
{reply, {ok, Id, Pid}, NewState}.
get_provider_list(#state{provider=Provider}=State) ->
Filter = fun({Id, Pid, _Mref}, Acc) ->
[{Id, Pid} | Acc]
end,
List = lists:foldl(Filter, [], Provider),
{reply, {ok, List}, State}.
get_provider(Id, #state{provider=Provider}=State) ->
case lists:keyfind(Id, 1, Provider) of
false -> {reply, {error, not_found}, State};
{Id, Pid, _MRef} -> {reply, {ok, Pid}, State}
end.
find_provider(Issuer, #state{provider=Provider}=State) ->
Filter = fun({_Id, Pid, _Mref}, List) ->
case oidcc_openid_provider:is_issuer(Issuer, Pid) of
true -> [ Pid | List];
_ -> List
end
end,
case lists:foldl(Filter, [], Provider) of
[Pid | _ ] -> {reply, {ok, Pid}, State};
[] -> {reply, {error, not_found}, State}
end.
start_provider(Id, Config) ->
oidcc_openid_provider_sup:add_openid_provider(Id, Config).
insert_provider(Id, Pid, #state{provider=Provider} = State) ->
MRef = monitor(process, Pid),
NewProvider = [{Id, Pid, MRef} | lists:keydelete(Id, 1, Provider)],
State#state{provider=NewProvider}.
get_unique_id(State) ->
Id = random_id(),
case is_unique_id(Id, State) of
true -> Id;
false -> get_unique_id(State)
end.
is_unique_id(Id, #state{provider=Provider}) ->
case lists:keyfind(Id, 1, Provider) of
false -> true;
_ -> false
end.
random_id() ->
random_id(5).
random_id(Length) ->
Random = try crypto:strong_rand_bytes(Length) of
Data -> Data
catch
low_entropy ->
timer:sleep(100),
random_id(Length)
end,
base64url:encode(Random).