Skip to content

Commit

Permalink
Support CLient Credential Flow
Browse files Browse the repository at this point in the history
  • Loading branch information
maennchen committed Jul 6, 2021
1 parent 295cc8c commit 7ee628a
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/oidcc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
-export([create_redirect_for_session/2]).
-export([retrieve_and_validate_token/2]).
-export([retrieve_and_validate_token/3]).
-export([retrieve_client_credential_token/1]).
-export([retrieve_client_credential_token/2]).
-export([retrieve_user_info/2]).
-export([retrieve_user_info/3]).
-export([retrieve_fresh_token/2]).
Expand Down Expand Up @@ -160,6 +162,27 @@ retrieve_and_validate_token(AuthCode, ProviderId, Config) ->
Error
end.

%% @doc
%% retrieve the token using the client credentials and directly validate the
%% result.
%%
%% the result is textual representation of the token and should be verified
%% using parse_and_validate_token/3
%% @end
retrieve_client_credential_token(ProviderId) ->
retrieve_client_credential_token(ProviderId, #{}).

retrieve_client_credential_token(ProviderId, Config) ->
{ok, Info} = get_openid_provider_info(ProviderId),
Scopes = scopes_to_bin(maps:get(scope, Config, []), <<>>),
QsBody = [{<<"grant_type">>, <<"client_credentials">>}],
case retrieve_a_token(QsBody, undefined, Info) of
{ok, Token} ->
{ok, oidcc_token:extract_token_map(Token, Scopes)};
Error ->
Error
end.

%% @doc
%% retrieve the informations of a user given by its token map or an access token
%%
Expand Down
63 changes: 63 additions & 0 deletions test/oidcc_test.erl
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,69 @@ retrieve_and_validate_token_test() ->
meck:unload(oidcc_token),
ok.

retrieve_client_credential_token_test() ->
MyPid = self(),
ClientId = <<"123">>,
ClientSecret = <<"secret">>,
TokenEndpoint = <<"https://my.provider/token">>,
TokenData = <<"TokenData">>,
AccessTokenMap =
#{expires => <<"3599">>,
hash => undefined,
token => <<"AccessToken">>},
ProviderId = <<"ID123">>,
AuthMethods = [<<"unsupporeted_auth">>, <<"client_secret_post">>],
ConfigFun =
fun(Pid) ->
Pid = MyPid,
{ok,
#{client_id => ClientId,
client_secret => ClientSecret,
token_endpoint => TokenEndpoint,
token_endpoint_auth_methods_supported => AuthMethods}}
end,
MapFun =
fun(Id) ->
case Id of
ProviderId ->
{ok, MyPid};
_ ->
{error, not_found}
end
end,
HttpFun =
fun(Method, Url, _Header, _ContentType, _Body) ->
Method = post,
Url = TokenEndpoint,
{ok,
#{status => 200,
header => [],
body => TokenData}}
end,
ExtractFun =
fun(Data, _Scopes) ->
Data = TokenData,
#{access => AccessTokenMap}
end,
ok = meck:new(oidcc_token),
ok = meck:expect(oidcc_token, extract_token_map, ExtractFun),
ok = meck:new(oidcc_openid_provider),
ok = meck:new(oidcc_openid_provider_mgr),
ok = meck:new(oidcc_http_util),
ok = meck:expect(oidcc_openid_provider, get_config, ConfigFun),
ok = meck:expect(oidcc_openid_provider_mgr, get_openid_provider, MapFun),
ok = meck:expect(oidcc_http_util, sync_http, HttpFun),
{ok, #{access := #{}}} = oidcc:retrieve_client_credential_token(ProviderId),
true = meck:validate(oidcc_token),
true = meck:validate(oidcc_openid_provider),
true = meck:validate(oidcc_openid_provider_mgr),
true = meck:validate(oidcc_http_util),
meck:unload(oidcc_openid_provider),
meck:unload(oidcc_openid_provider_mgr),
meck:unload(oidcc_http_util),
meck:unload(oidcc_token),
ok.

retrieve_user_info_test() ->
MyPid = self(),
ProviderId = <<"6">>,
Expand Down

0 comments on commit 7ee628a

Please sign in to comment.