TD-104: Update token-keeper-client (#3)

This commit is contained in:
Alexey S 2022-02-24 12:36:27 +03:00 committed by GitHub
parent 78a94a2af4
commit ba45f12071
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 100 additions and 63 deletions

View File

@ -6,7 +6,7 @@ on:
- 'master'
- 'epic/**'
pull_request:
branches: [ '**' ]
branches: ['**']
env:
REGISTRY: ghcr.io

View File

@ -6,7 +6,7 @@ on:
- 'master'
- 'epic/**'
pull_request:
branches: [ '**' ]
branches: ['**']
jobs:
setup:

View File

@ -18,7 +18,7 @@
-type token_type() :: bearer.
-type preauth_context() :: {unauthorized, {token_type(), token_keeper_client:token()}}.
-type auth_context() :: {authorized, token_keeper_auth_data:auth_data()}.
-type auth_context() :: {authorized, token_keeper_client:auth_data()}.
-type resolution() :: allowed | forbidden.
-type consumer() :: client | merchant | provider.
-type token_spec() :: #{
@ -26,7 +26,7 @@
scope := {invoice | invoice_template | customer, binary()},
shop => binary(),
lifetime => pos_integer() | unlimited,
metadata => token_keeper_auth_data:metadata()
metadata => token_keeper_client:metadata()
}.
-export_type([preauth_context/0]).
@ -40,6 +40,8 @@
-define(AUTHORIZED(Ctx), {authorized, Ctx}).
-define(UNAUTHORIZED(Ctx), {unauthorized, Ctx}).
-define(TOKEN_KEEPER_AUTHORITY, generic_access_token).
%%
%% API functions
%%
@ -54,20 +56,20 @@ get_subject_id(AuthContext) ->
end.
-spec get_party_id(auth_context()) -> binary() | undefined.
get_party_id(?AUTHORIZED(AuthData)) ->
get_metadata(get_metadata_mapped_key(party_id), token_keeper_auth_data:get_metadata(AuthData)).
get_party_id(?AUTHORIZED(#{metadata := Metadata})) ->
get_metadata(get_metadata_mapped_key(party_id), Metadata).
-spec get_user_id(auth_context()) -> binary() | undefined.
get_user_id(?AUTHORIZED(AuthData)) ->
get_metadata(get_metadata_mapped_key(user_id), token_keeper_auth_data:get_metadata(AuthData)).
get_user_id(?AUTHORIZED(#{metadata := Metadata})) ->
get_metadata(get_metadata_mapped_key(user_id), Metadata).
-spec get_user_email(auth_context()) -> binary() | undefined.
get_user_email(?AUTHORIZED(AuthData)) ->
get_metadata(get_metadata_mapped_key(user_email), token_keeper_auth_data:get_metadata(AuthData)).
get_user_email(?AUTHORIZED(#{metadata := Metadata})) ->
get_metadata(get_metadata_mapped_key(user_email), Metadata).
-spec get_consumer(auth_context()) -> consumer().
get_consumer(?AUTHORIZED(AuthData)) ->
case get_metadata(get_metadata_mapped_key(token_consumer), token_keeper_auth_data:get_metadata(AuthData)) of
get_consumer(?AUTHORIZED(#{metadata := Metadata})) ->
case get_metadata(get_metadata_mapped_key(token_consumer), Metadata) of
<<"merchant">> -> merchant;
<<"client">> -> client;
<<"provider">> -> provider;
@ -85,7 +87,7 @@ preauthorize_api_key(ApiKey) ->
{error, Error}
end.
-spec authorize_api_key(preauth_context(), token_keeper_client:source_context(), woody_context:ctx()) ->
-spec authorize_api_key(preauth_context(), token_keeper_client:token_context(), woody_context:ctx()) ->
{ok, auth_context()} | {error, _Reason}.
authorize_api_key(?UNAUTHORIZED({TokenType, Token}), TokenContext, WoodyContext) ->
authorize_token_by_type(TokenType, Token, TokenContext, WoodyContext).
@ -113,9 +115,11 @@ authorize_operation(Prototypes, ProcessingContext) ->
issue_access_token(TokenSpec, WoodyContext) ->
ContextFragment = create_context_fragment(TokenSpec),
Metadata = create_metadata(TokenSpec),
%%TODO InvoiceTemplateAccessTokens are technically not ephemeral and should become so in the future
AuthData = token_keeper_client:create_ephemeral(ContextFragment, Metadata, WoodyContext),
token_keeper_auth_data:get_token(AuthData).
%% @TODO for now access tokens are only ephemeral, fix this for compact stuff
% %%TODO InvoiceTemplateAccessTokens are technically not ephemeral and should become so in the future
AuthClient = token_keeper_client:ephemeral_authority(?TOKEN_KEEPER_AUTHORITY, WoodyContext),
{ok, #{token := Token}} = token_keeper_authority_ephemeral:create(ContextFragment, Metadata, AuthClient),
Token.
%%
%% Internal functions
@ -197,11 +201,12 @@ create_metadata(TokenSpec) ->
extract_auth_context(#{swagger_context := #{auth_context := AuthContext}}) ->
AuthContext.
get_token_keeper_fragment(?AUTHORIZED(AuthData)) ->
token_keeper_auth_data:get_context_fragment(AuthData).
get_token_keeper_fragment(?AUTHORIZED(#{context := Context})) ->
Context.
authorize_token_by_type(bearer, Token, TokenContext, WoodyContext) ->
case token_keeper_client:get_by_token(Token, TokenContext, WoodyContext) of
Authenticator = token_keeper_client:authenticator(WoodyContext),
case token_keeper_authenticator:authenticate(Token, TokenContext, Authenticator) of
{ok, AuthData} ->
{ok, ?AUTHORIZED(AuthData)};
{error, TokenKeeperError} ->

View File

@ -8,7 +8,7 @@
%%
-spec gather_context_fragments(
TokenContextFragment :: token_keeper_auth_data:context_fragment(),
TokenContextFragment :: token_keeper_client:context_fragment(),
UserID :: binary() | undefined,
RequestContext :: swag_server:request_context(),
WoodyContext :: woody_context:ctx()

View File

@ -224,7 +224,7 @@ make_token_context(#{cowboy_req := CowboyReq}) ->
Origin when is_binary(Origin) ->
#{request_origin => Origin};
undefined ->
undefined
#{}
end.
create_processing_context(OperationID, SwaggerContext, WoodyContext, HandlerOpts) ->

View File

@ -12,7 +12,7 @@
-type sup_or_config() :: capi_ct_helper:sup_or_config().
-type app_name() :: capi_ct_helper:app_name().
-type token_handler() :: fun(('GetByToken', tuple()) -> term() | no_return()).
-type token_handler() :: fun(('Authenticate' | 'Create', tuple()) -> term() | no_return()).
-export([mock_token/2]).
-export([mock_not_found/1]).
@ -21,7 +21,6 @@
-export([mock_invoice_access_token/3]).
-export([mock_invoice_template_access_token/3]).
-export([mock_customer_access_token/3]).
-export([make_token_handler/1]).
-spec mock_token(token_handler(), sup_or_config()) -> list(app_name()).
mock_token(HandlerFun, SupOrConfig) ->
@ -29,9 +28,14 @@ mock_token(HandlerFun, SupOrConfig) ->
capi_ct_helper:mock_services_(
[
{
token_keeper,
{tk_token_keeper_thrift, 'TokenKeeper'},
token_authenticator,
{tk_token_keeper_thrift, 'TokenAuthenticator'},
HandlerFun
},
{
ephememeral_token_authority,
{tk_token_keeper_thrift, 'EphemeralTokenAuthority'},
make_authority_handler()
}
],
SupOrConfig
@ -40,8 +44,18 @@ mock_token(HandlerFun, SupOrConfig) ->
start_client(ServiceURLs) ->
capi_ct_helper:start_app(token_keeper_client, [
{service_client, #{
url => maps:get(token_keeper, ServiceURLs)
{service_clients, #{
authenticator => #{
url => maps:get(token_authenticator, ServiceURLs)
},
authorities => #{
ephemeral => #{
generic_access_token => #{
url => maps:get(ephememeral_token_authority, ServiceURLs)
}
},
offline => #{}
}
}}
]).
@ -49,11 +63,11 @@ start_client(ServiceURLs) ->
-spec mock_not_found(sup_or_config()) -> list(app_name()).
mock_not_found(SupOrConfig) ->
mock_token(fun('GetByToken', {_, _}) -> {throwing, #token_keeper_AuthDataNotFound{}} end, SupOrConfig).
mock_token(fun('Authenticate', {_, _}) -> {throwing, #token_keeper_AuthDataNotFound{}} end, SupOrConfig).
-spec mock_user_session_token(sup_or_config()) -> list(app_name()).
mock_user_session_token(SupOrConfig) ->
Handler = make_token_handler(fun() ->
Handler = make_authenticator_handler(fun() ->
UserParams = #{
id => ?USER_ID,
realm => #{id => <<"external">>},
@ -70,7 +84,7 @@ mock_user_session_token(SupOrConfig) ->
-spec mock_api_key_token(binary(), sup_or_config()) -> list(app_name()).
mock_api_key_token(PartyID, SupOrConfig) ->
Handler = make_token_handler(fun() ->
Handler = make_authenticator_handler(fun() ->
AuthParams = #{
method => <<"ApiKeyToken">>,
token => #{id => ?STRING},
@ -82,7 +96,7 @@ mock_api_key_token(PartyID, SupOrConfig) ->
-spec mock_invoice_access_token(binary(), binary(), sup_or_config()) -> list(app_name()).
mock_invoice_access_token(PartyID, InvoiceID, SupOrConfig) ->
Handler = make_token_handler(fun() ->
Handler = make_authenticator_handler(fun() ->
AuthParams = #{
method => <<"InvoiceAccessToken">>,
expiration => posix_to_rfc3339(lifetime_to_expiration(?TOKEN_LIFETIME)),
@ -97,7 +111,7 @@ mock_invoice_access_token(PartyID, InvoiceID, SupOrConfig) ->
-spec mock_invoice_template_access_token(binary(), binary(), sup_or_config()) -> list(app_name()).
mock_invoice_template_access_token(PartyID, InvoiceTemplateID, SupOrConfig) ->
Handler = make_token_handler(fun() ->
Handler = make_authenticator_handler(fun() ->
AuthParams = #{
method => <<"InvoiceAccessToken">>,
expiration => posix_to_rfc3339(unlimited),
@ -110,7 +124,7 @@ mock_invoice_template_access_token(PartyID, InvoiceTemplateID, SupOrConfig) ->
-spec mock_customer_access_token(binary(), binary(), sup_or_config()) -> list(app_name()).
mock_customer_access_token(PartyID, CustomerID, SupOrConfig) ->
Handler = make_token_handler(fun() ->
Handler = make_authenticator_handler(fun() ->
AuthParams = #{
method => <<"CustomerAccessToken">>,
expiration => posix_to_rfc3339(lifetime_to_expiration(?TOKEN_LIFETIME)),
@ -123,28 +137,31 @@ mock_customer_access_token(PartyID, CustomerID, SupOrConfig) ->
%%
-spec make_token_handler(function()) -> token_handler().
make_token_handler(Handler) ->
fun
('GetByToken', {Token, _}) ->
{Authority, ContextFragment, Metadata} = Handler(),
AuthData = #token_keeper_AuthData{
token = Token,
status = active,
context = ContextFragment,
authority = Authority,
metadata = combine_metadata(Metadata)
},
{ok, AuthData};
('CreateEphemeral', {ContextFragment, Metadata}) ->
AuthData = #token_keeper_AuthData{
token = ?API_TOKEN,
status = active,
context = ContextFragment,
authority = ?TK_AUTHORITY_APIKEYMGMT,
metadata = Metadata
},
{ok, AuthData}
-spec make_authenticator_handler(function()) -> token_handler().
make_authenticator_handler(Handler) ->
fun('Authenticate', {Token, _}) ->
{Authority, ContextFragment, Metadata} = Handler(),
AuthData = #token_keeper_AuthData{
token = Token,
status = active,
context = ContextFragment,
authority = Authority,
metadata = combine_metadata(Metadata)
},
{ok, AuthData}
end.
-spec make_authority_handler() -> token_handler().
make_authority_handler() ->
fun('Create', {ContextFragment, Metadata}) ->
AuthData = #token_keeper_AuthData{
token = ?API_TOKEN,
status = active,
context = ContextFragment,
authority = ?TK_AUTHORITY_APIKEYMGMT,
metadata = Metadata
},
{ok, AuthData}
end.
%%

View File

@ -184,12 +184,27 @@
]},
{token_keeper_client, [
{service_client, #{
url => <<"http://token-keeper:8022/">>,
timeout => 1000,
retries => #{
'GetByToken' => {linear, 3, 100},
'_' => finish
{service_clients, #{
authenticator => #{
url => <<"http://token-keeper:8022/v2/authenticator">>,
timeout => 1000,
retries => #{
'Authenticate' => {linear, 3, 100},
'_' => finish
}
},
authorities => #{
ephemeral => #{
generic_access_token => #{
url => <<"http://token-keeper:8022/v2/authority/dev.vality.capi.access">>,
timeout => 1000,
retries => #{
'Create' => {linear, 3, 100},
'_' => finish
}
}
},
offline => #{}
}
}}
]},

View File

@ -131,11 +131,11 @@
1},
{<<"token_keeper_client">>,
{git,"https://github.com/valitydev/token-keeper-client.git",
{ref,"27158ea5d3e3c74f0090f8d2ac3f2ca52ab39584"}},
{ref,"d3673e72c4c3480b4b8ddff85f1450a6ffd5dd34"}},
0},
{<<"token_keeper_proto">>,
{git,"https://github.com/valitydev/token-keeper-proto.git",
{ref,"c7f48d24a561c95b8135d3b07fd2ff55a62eb308"}},
{ref,"e52cb1ca0ea9ca5fbf3792ae211ae87bdc1d4cc5"}},
1},
{<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},2},
{<<"woody">>,