ED-222: Simplify metadata format (#14)

This commit is contained in:
Alexey 2021-08-16 16:56:17 +03:00 committed by GitHub
parent 11f8f23670
commit 8dca9ed3c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 267 additions and 150 deletions

View File

@ -71,20 +71,23 @@
%% Which jwt key to use for signing for this authority
%% You can only use keys that have the same authority configured for them
signer => test,
%% Storage configuration (NOT IMPLEMENTED)
storage => {machinegun, #{}},
%% Where to fetch authdata for tokens issued by this authority
authdata_sources => [
%% Fetch from storage
{storage,
%% Use token claims as storage
{claim, #{
%% Enable compatability with legacy issued tokens when getting from storage
compatability => {true, <<"test.rbkmoney.apikeymgmt">>}
%% Fetch from claim
{claim, #{
%% Enable compatibility with legacy issued tokens when getting from storage
compatibility => {true, #{
%% Where to put metadata
metadata_mappings => #{
party_id => <<"test.rbkmoney.party.id">>,
consumer => <<"test.rbkmoney.capi.consumer">>
}
}}
},
{storage,
%% Use machinegun as storage (NOT IMPLEMENTED)
machinegun
},
}},
%% Fetch from storage (configured for authority) (NOT IMPLEMENTED)
storage,
%% Create a new bouncer context using token data
{extract, #{
%% Configuration for how to extract said context
@ -102,15 +105,21 @@
{detect_token, #{
%% phony_api_key options to use (can be used standalone)
phony_api_key_opts => #{
%% What to use as metadata namespace
metadata_ns => <<"test.rbkmoney.apikeymgmt">>
%% Where to put metadata
metadata_mappings => #{
party_id => <<"test.rbkmoney.party.id">>
}
},
%% user_session_token options to use (can be used standalone)
user_session_token_opts => #{
%% Realm of the user
user_realm => <<"external">>,
%% What to use as metadata namespace
metadata_ns => <<"test.rbkmoney.keycloak">>
%% Where to put metadata
metadata_mappings => #{
user_id => <<"test.rbkmoney.user.id">>,
user_email => <<"test.rbkmoney.user.email">>,
user_realm => <<"test.rbkmoney.user.realm">>
}
},
%% List of origins using which we perform token classification
user_session_token_origins => [<<"http://localhost">>]

View File

@ -57,15 +57,15 @@
{<<"snowflake">>,
{git,"https://github.com/rbkmoney/snowflake.git",
{ref,"de159486ef40cec67074afe71882bdc7f7deab72"}},
1},
0},
{<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.6">>},2},
{<<"thrift">>,
{git,"https://github.com/rbkmoney/thrift_erlang.git",
{ref,"846a0819d9b6d09d0c31f160e33a78dbad2067b4"}},
0},
{<<"token_keeper_proto">>,
{git,"git@github.com:rbkmoney/token-keeper-proto.git",
{ref,"48a18d87ea2443540272c80213f7612beea6af9c"}},
{git,"https://github.com/rbkmoney/token-keeper-proto.git",
{ref,"15781716691a72de8c8f065c11c5b08173fc8434"}},
0},
{<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},2},
{<<"woody">>,

View File

@ -10,7 +10,7 @@
%% API Types
-type authdata_source() :: storage_source() | extractor_source().
-type authdata_source() :: storage_source() | claim_source() | extractor_source().
-type sourced_authdata() :: #{
id => tk_authority:authdata_id(),
status := tk_authority:status(),
@ -25,12 +25,14 @@
%% Internal types
-type storage_source() :: {storage, tk_authdata_source_storage:source_opts()}.
-type claim_source() :: {claim, tk_authdata_source_claim:source_opts()}.
-type extractor_source() :: maybe_opts(extractor, tk_authdata_source_extractor:source_opts()).
-type maybe_opts(Source, Opts) :: Source | {Source, Opts}.
-type source_opts() ::
tk_authdata_source_extractor:source_opts()
| tk_authdata_source_claim:source_opts()
| tk_authdata_source_storage:source_opts().
%% API functions
@ -50,5 +52,7 @@ get_source_opts(Source) when is_atom(Source) ->
get_source_handler(storage) ->
tk_authdata_source_storage;
get_source_handler(claim) ->
tk_authdata_source_claim;
get_source_handler(extract) ->
tk_authdata_source_extractor.

View File

@ -0,0 +1,27 @@
-module(tk_authdata_source_claim).
-behaviour(tk_authdata_source).
%% Behaviour
-export([get_authdata/2]).
%%
-type stored_authdata() :: tk_storage:storable_authdata().
-type source_opts() :: tk_token_claim_utils:decode_opts().
-export_type([stored_authdata/0]).
-export_type([source_opts/0]).
%% Behaviour functions
-spec get_authdata(tk_token_jwt:t(), source_opts()) -> stored_authdata() | undefined.
get_authdata(Token, Opts) ->
Claims = tk_token_jwt:get_claims(Token),
case tk_token_claim_utils:decode_authdata(Claims, Opts) of
{ok, AuthData} ->
AuthData;
{error, Reason} ->
_ = logger:warning("Failed claim get: ~p", [Reason]),
undefined
end.

View File

@ -8,25 +8,28 @@
%%
-type stored_authdata() :: tk_storage:storable_authdata().
-type source_opts() :: claim_storage().
-type source_opts() :: tk_storage:storage_opts().
-export_type([stored_authdata/0]).
-export_type([source_opts/0]).
%%
-type claim_storage() :: maybe_opts(claim, tk_storage_claim:storage_opts()).
-type maybe_opts(Source, Opts) :: Source | {Source, Opts}.
%% Behaviour functions
-spec get_authdata(tk_token_jwt:t(), source_opts()) -> stored_authdata() | undefined.
get_authdata(Token, StorageOpts) ->
Claims = tk_token_jwt:get_claims(Token),
case tk_storage:get_by_claims(Claims, StorageOpts) of
{ok, AuthData} ->
AuthData;
AuthDataID = get_authdata_id(Claims),
case tk_storage:get(AuthDataID, StorageOpts) of
%% Not implemented
%% {ok, AuthData} ->
%% AuthData;
{error, Reason} ->
_ = logger:warning("Failed storage get: ~p", [Reason]),
undefined
end.
%%
get_authdata_id(_Claims) ->
%% Not implemented
<<>>.

View File

@ -31,8 +31,7 @@
-type authdata_id() :: binary().
-type status() :: active | revoked.
-type encoded_context_fragment() :: tk_context_thrift:'ContextFragment'().
-type metadata() :: #{metadata_ns() => #{binary() => binary()}}.
-type metadata_ns() :: binary().
-type metadata() :: #{binary() => binary()}.
-export_type([authority/0]).
@ -41,7 +40,6 @@
-export_type([status/0]).
-export_type([encoded_context_fragment/0]).
-export_type([metadata/0]).
-export_type([metadata_ns/0]).
-export_type([autority_id/0]).
%% API Functions

View File

@ -13,7 +13,9 @@
-type extractor_opts() :: #{
domain := binary(),
metadata_ns := binary()
metadata_mappings := #{
party_id := binary()
}
}.
-export_type([extractor_opts/0]).
@ -26,7 +28,16 @@ get_context(Token, ExtractorOpts) ->
case extract_invoice_template_rights(Token, ExtractorOpts) of
{ok, InvoiceTemplateID} ->
BCtx = create_bouncer_ctx(tk_token_jwt:get_token_id(Token), UserID, InvoiceTemplateID),
{BCtx, wrap_metadata(get_metadata(Token), ExtractorOpts)};
{BCtx,
make_metadata(
#{
%% @TEMP: This is a temporary hack.
%% When some external services will stop requiring woody user
%% identity to be present it must be removed too
party_id => tk_token_jwt:get_subject_id(Token)
},
ExtractorOpts
)};
{error, Reason} ->
_ = logger:warning("Failed to extract invoice template rights: ~p", [Reason]),
undefined
@ -34,16 +45,6 @@ get_context(Token, ExtractorOpts) ->
%%
get_metadata(Token) ->
%% @TEMP: This is a temporary hack.
%% When some external services will stop requiring woody user identity to be present it must be removed too
case tk_token_jwt:get_subject_id(Token) of
UserID when UserID =/= undefined ->
#{<<"party_id">> => UserID};
undefined ->
undefined
end.
extract_invoice_template_rights(TokenContext, ExtractorOpts) ->
Domain = maps:get(domain, ExtractorOpts),
case get_acl(Domain, get_resource_hierarchy(), TokenContext) of
@ -106,9 +107,9 @@ create_bouncer_ctx(TokenID, UserID, InvoiceTemplateID) ->
bouncer_context_helpers:empty()
).
wrap_metadata(Metadata, ExtractorOpts) ->
MetadataNS = maps:get(metadata_ns, ExtractorOpts),
#{MetadataNS => Metadata}.
make_metadata(Metadata, ExtractorOpts) ->
Mappings = maps:get(metadata_mappings, ExtractorOpts),
tk_utils:remap(genlib_map:compact(Metadata), Mappings).
get_resource_hierarchy() ->
#{

View File

@ -6,7 +6,9 @@
%%
-type extractor_opts() :: #{
metadata_ns := binary()
metadata_mappings := #{
party_id := binary()
}
}.
-export_type([extractor_opts/0]).
@ -15,20 +17,26 @@
-spec get_context(tk_token_jwt:t(), extractor_opts()) -> tk_extractor:extracted_context().
get_context(Token, ExtractorOpts) ->
UserID = tk_token_jwt:get_subject_id(Token),
PartyID = tk_token_jwt:get_subject_id(Token),
Acc0 = bouncer_context_helpers:empty(),
Acc1 = bouncer_context_helpers:add_auth(
#{
method => <<"ApiKeyToken">>,
token => #{id => tk_token_jwt:get_token_id(Token)},
scope => [#{party => #{id => UserID}}]
scope => [#{party => #{id => PartyID}}]
},
Acc0
),
{Acc1, wrap_metadata(#{<<"party_id">> => UserID}, ExtractorOpts)}.
{Acc1,
make_metadata(
#{
party_id => PartyID
},
ExtractorOpts
)}.
%%
wrap_metadata(Metadata, ExtractorOpts) ->
MetadataNS = maps:get(metadata_ns, ExtractorOpts),
#{MetadataNS => Metadata}.
make_metadata(Metadata, ExtractorOpts) ->
Mappings = maps:get(metadata_mappings, ExtractorOpts),
tk_utils:remap(genlib_map:compact(Metadata), Mappings).

View File

@ -6,7 +6,11 @@
%%
-type extractor_opts() :: #{
metadata_ns := binary(),
metadata_mappings := #{
user_id := binary(),
user_email := binary(),
user_realm := binary()
},
user_realm := binary()
}.
@ -38,12 +42,12 @@ get_context(Token, ExtractorOpts) ->
Acc1
),
{Acc2,
wrap_metadata(
genlib_map:compact(#{
<<"user_id">> => UserID,
<<"user_email">> => Email,
<<"user_realm">> => UserRealm
}),
make_metadata(
#{
user_id => UserID,
user_email => Email,
user_realm => UserRealm
},
ExtractorOpts
)}.
@ -54,6 +58,6 @@ make_auth_expiration(Timestamp) when is_integer(Timestamp) ->
make_auth_expiration(Expiration) when Expiration =:= unlimited; Expiration =:= undefined ->
undefined.
wrap_metadata(Metadata, ExtractorOpts) ->
MetadataNS = maps:get(metadata_ns, ExtractorOpts),
#{MetadataNS => Metadata}.
make_metadata(Metadata, ExtractorOpts) ->
Mappings = maps:get(metadata_mappings, ExtractorOpts),
tk_utils:remap(genlib_map:compact(Metadata), Mappings).

View File

@ -1,19 +1,19 @@
-module(tk_storage).
-export([get/2]).
-export([get_by_claims/2]).
-export([store/2]).
-export([revoke/2]).
%%
-callback get(authdata_id(), opts()) -> {ok, tk_storage:storable_authdata()} | {error, _Reason}.
-callback get_by_claims(claims(), opts()) -> {ok, tk_storage:storable_authdata()} | {error, _Reason}.
-callback store(tk_storage:storable_authdata(), opts()) -> {ok, claims()} | {error, _Reason}.
-callback revoke(authdata_id(), opts()) -> ok | {error, _Reason}.
%%
-type storage_opts() :: {storage(), opts()} | storage().
-type storable_authdata() :: #{
id => tk_authority:authdata_id(),
status := tk_authority:status(),
@ -23,15 +23,15 @@
}.
-export_type([storable_authdata/0]).
-export_type([storage_opts/0]).
%%
-type authdata_id() :: tk_authority:authdata_id().
-type claims() :: tk_token_jwt:claims().
-type storage_opts() :: {storage(), opts()} | storage().
-type storage() :: claim.
-type opts() :: tk_storage_claim:storage_opts().
-type storage() :: machinegun.
-type opts() :: tk_storage_machinegun:storage_opts().
%%
@ -41,12 +41,6 @@ get(DataID, StorageOpts) ->
Handler = get_storage_handler(Storage),
Handler:get(DataID, Opts).
-spec get_by_claims(claims(), storage_opts()) -> {ok, storable_authdata()} | {error, _Reason}.
get_by_claims(Claims, StorageOpts) ->
{Storage, Opts} = get_storage_opts(StorageOpts),
Handler = get_storage_handler(Storage),
Handler:get_by_claims(Claims, Opts).
-spec store(storable_authdata(), storage_opts()) -> {ok, claims()} | {error, _Reason}.
store(AuthData, StorageOpts) ->
{Storage, Opts} = get_storage_opts(StorageOpts),
@ -61,8 +55,8 @@ revoke(DataID, StorageOpts) ->
%%
get_storage_handler(claim) ->
tk_storage_claim.
get_storage_handler(machinegun) ->
tk_storage_machinegun.
get_storage_opts({_Storage, _Opts} = StorageOpts) ->
StorageOpts;

View File

@ -1,23 +1,27 @@
-module(tk_storage_claim).
-module(tk_token_claim_utils).
-include_lib("token_keeper_proto/include/tk_context_thrift.hrl").
-behaviour(tk_storage).
-export([get/2]).
-export([get_by_claims/2]).
-export([store/2]).
-export([revoke/2]).
-export([decode_authdata/2]).
-export([encode_authdata/1]).
-type storage_opts() :: #{
compatability => {true, MetadataNS :: binary()} | false
-type decode_opts() :: #{
compatibility => {true, compatibility_opts()} | false
}.
-export_type([storage_opts/0]).
-type compatibility_opts() :: #{
metadata_mappings := #{
party_id := binary(),
token_consumer := binary()
}
}.
-export_type([decode_opts/0]).
-export_type([compatibility_opts/0]).
%%
-type storable_authdata() :: tk_storage:storable_authdata().
-type authdata_id() :: tk_authority:authdata_id().
-type claim() :: tk_token_jwt:claim().
-type claims() :: tk_token_jwt:claims().
@ -30,14 +34,10 @@
%%
-spec get(authdata_id(), storage_opts()) -> {error, not_found}.
get(_DataID, _Opts) ->
{error, not_found}.
-spec get_by_claims(claims(), storage_opts()) ->
-spec decode_authdata(claims(), decode_opts()) ->
{ok, storable_authdata()}
| {error, not_found | {claim_decode_error, {unsupported, claim()} | {malformed, binary()}}}.
get_by_claims(#{?CLAIM_BOUNCER_CTX := BouncerClaim} = Claims, Opts) ->
decode_authdata(#{?CLAIM_BOUNCER_CTX := BouncerClaim} = Claims, Opts) ->
case decode_bouncer_claim(BouncerClaim) of
{ok, ContextFragment} ->
case get_metadata(Claims, Opts) of
@ -49,21 +49,17 @@ get_by_claims(#{?CLAIM_BOUNCER_CTX := BouncerClaim} = Claims, Opts) ->
{error, Reason} ->
{error, {claim_decode_error, Reason}}
end;
get_by_claims(_Claims, _Opts) ->
decode_authdata(_Claims, _Opts) ->
{error, not_found}.
-spec store(storable_authdata(), storage_opts()) -> {ok, claims()}.
store(#{context := ContextFragment} = AuthData, _Opts) ->
{ok, #{
-spec encode_authdata(storable_authdata()) -> claims().
encode_authdata(#{context := ContextFragment} = AuthData) ->
#{
?CLAIM_BOUNCER_CTX => encode_bouncer_claim(ContextFragment),
?CLAIM_TK_METADATA => encode_metadata(AuthData)
}}.
}.
-spec revoke(authdata_id(), storage_opts()) -> {error, storage_immutable}.
revoke(_DataID, _Opts) ->
{error, storage_immutable}.
%% Internal functions
%%
decode_bouncer_claim(#{
?CLAIM_CTX_TYPE := ?CLAIM_CTX_TYPE_V1_THRIFT_BINARY,
@ -101,8 +97,8 @@ encode_metadata(#{}) ->
get_metadata(#{?CLAIM_TK_METADATA := Metadata}, _Opts) ->
{ok, Metadata};
get_metadata(Claims, #{compatability := {true, MetadataNS}}) ->
{ok, wrap_metadata(create_metadata(Claims), MetadataNS)};
get_metadata(Claims, #{compatibility := {true, CompatOpts}}) ->
{ok, create_metadata(Claims, CompatOpts)};
get_metadata(_Claims, _Opts) ->
{error, no_metadata_claim}.
@ -113,21 +109,11 @@ create_authdata(ContextFragment, Metadata) ->
metadata => Metadata
}).
create_metadata(Claims) ->
Metadata = maps:with(get_passthrough_claim_names(), Claims),
%% TODO: This is a temporary hack.
%% When some external services will stop requiring woody user identity to be present it must be removed too
genlib_map:compact(Metadata#{
<<"party_id">> => maps:get(<<"sub">>, Claims, undefined)
}).
wrap_metadata(Metadata, _MetadataNS) when map_size(Metadata) =:= 0 ->
undefined;
wrap_metadata(Metadata, MetadataNS) ->
#{MetadataNS => Metadata}.
get_passthrough_claim_names() ->
[
%% token consumer
<<"cons">>
].
create_metadata(Claims, CompatOpts) ->
Metadata = #{
%% TODO: This is a temporary hack.
%% When some external services will stop requiring woody user identity to be present it must be removed too
party_id => maps:get(<<"sub">>, Claims, undefined),
consumer => maps:get(<<"cons">>, Claims, undefined)
},
tk_utils:remap(genlib_map:compact(Metadata), maps:get(metadata_mappings, CompatOpts)).

64
src/tk_utils.erl Normal file
View File

@ -0,0 +1,64 @@
-module(tk_utils).
-export([remap/2]).
-spec remap(Map :: map(), KeyMap :: map()) -> map().
remap(Map, KeyMap) ->
maps:fold(
fun(Key, Value, Acc) ->
case maps:get(Key, KeyMap, undefined) of
NewKey when NewKey =/= undefined ->
Acc#{NewKey => Value};
undefined ->
error({badarg, {no_mapping, Key}})
end
end,
maps:new(),
Map
).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-spec test() -> _.
-spec remap_test() -> _.
remap_test() ->
?assertEqual(
#{
<<"a">> => a,
<<"b">> => b,
<<"c">> => c
},
remap(
#{
a => a,
b => b,
c => c
},
#{
a => <<"a">>,
b => <<"b">>,
c => <<"c">>
}
)
).
-spec remap_no_mapping_test() -> _.
remap_no_mapping_test() ->
?assertError(
{badarg, {no_mapping, c}},
remap(
#{
a => a,
b => b,
c => c
},
#{
a => <<"a">>,
b => <<"b">>
}
)
).
-endif.

View File

@ -34,8 +34,8 @@ handle_function_('CreateEphemeral' = Op, {ContextFragment, Metadata}, State) ->
_ = handle_beat(Op, started, State),
Authority = get_autority_config(get_issuing_authority()),
AuthData = issue_auth_data(ContextFragment, Metadata, Authority),
{ok, StorageClaims} = tk_storage:store(AuthData, claim),
{ok, Token} = tk_token_jwt:issue(unique_id(), StorageClaims, get_signer(Authority)),
Claims = tk_token_claim_utils:encode_authdata(AuthData),
{ok, Token} = tk_token_jwt:issue(unique_id(), Claims, get_signer(Authority)),
EncodedAuthData = encode_auth_data(AuthData#{token => Token}),
_ = handle_beat(Op, succeeded, State),
{ok, EncodedAuthData};

View File

@ -37,20 +37,17 @@
-define(CONFIG(Key, C), (element(2, lists:keyfind(Key, 1, C)))).
-define(TK_META_NS_KEYCLOAK, <<"test.rbkmoney.token-keeper">>).
-define(TK_META_NS_APIKEYMGMT, <<"test.rbkmoney.apikeymgmt">>).
-define(META_PARTY_ID, <<"test.rbkmoney.party.id">>).
-define(META_USER_ID, <<"test.rbkmoney.user.id">>).
-define(META_USER_EMAIL, <<"test.rbkmoney.user.email">>).
-define(META_USER_REALM, <<"test.rbkmoney.user.realm">>).
-define(META_CAPI_CONSUMER, <<"test.rbkmoney.capi.consumer">>).
-define(TK_AUTHORITY_KEYCLOAK, <<"test.rbkmoney.keycloak">>).
-define(TK_AUTHORITY_CAPI, <<"test.rbkmoney.capi">>).
-define(TK_RESOURCE_DOMAIN, <<"test-domain">>).
-define(METADATA(Authority, Metadata), #{Authority := Metadata}).
-define(PARTY_METADATA(Authority, SubjectID), ?METADATA(Authority, #{<<"party_id">> := SubjectID})).
-define(USER_METADATA(Authority, SubjectID, Email),
?METADATA(Authority, #{<<"user_id">> := SubjectID, <<"user_email">> := Email})
).
-define(TOKEN_SOURCE_CONTEXT(), ?TOKEN_SOURCE_CONTEXT(<<"http://spanish.inquisition">>)).
-define(TOKEN_SOURCE_CONTEXT(SourceURL), #token_keeper_TokenSourceContext{request_origin = SourceURL}).
@ -131,11 +128,17 @@ init_per_group(detect_token_type = Name, C) ->
methods => [
{detect_token, #{
phony_api_key_opts => #{
metadata_ns => ?TK_META_NS_APIKEYMGMT
metadata_mappings => #{
party_id => ?META_PARTY_ID
}
},
user_session_token_opts => #{
user_realm => <<"external">>,
metadata_ns => ?TK_META_NS_KEYCLOAK
metadata_mappings => #{
user_id => ?META_USER_ID,
user_email => ?META_USER_EMAIL,
user_realm => ?META_USER_REALM
}
},
user_session_token_origins => [?USER_TOKEN_SOURCE]
}}
@ -160,10 +163,15 @@ init_per_group(claim_only = Name, C) ->
claim_only => #{
id => ?TK_AUTHORITY_CAPI,
authdata_sources => [
{storage,
{claim, #{
compatability => {true, ?TK_META_NS_APIKEYMGMT}
}}}
{claim, #{
compatibility =>
{true, #{
metadata_mappings => #{
party_id => ?META_PARTY_ID,
consumer => ?META_CAPI_CONSUMER
}
}}
}}
]
}
}}
@ -183,15 +191,22 @@ init_per_group(invoice_template_access_token = Name, C) ->
invoice_tpl_authority => #{
id => ?TK_AUTHORITY_CAPI,
authdata_sources => [
{storage,
{claim, #{
compatability => {true, ?TK_META_NS_APIKEYMGMT}
}}},
{claim, #{
compatibility =>
{true, #{
metadata_mappings => #{
party_id => ?META_PARTY_ID,
token_consumer => ?META_CAPI_CONSUMER
}
}}
}},
{extract, #{
methods => [
{invoice_template_access_token, #{
domain => ?TK_RESOURCE_DOMAIN,
metadata_ns => ?TK_META_NS_APIKEYMGMT
metadata_mappings => #{
party_id => ?META_PARTY_ID
}
}}
]
}}
@ -218,7 +233,7 @@ init_per_group(issuing = Name, C) ->
id => ?TK_AUTHORITY_CAPI,
signer => test,
authdata_sources => [
{storage, claim}
claim
]
}
}}
@ -340,7 +355,7 @@ detect_api_key_test(C) ->
token = Token,
status = active,
context = Context,
metadata = ?PARTY_METADATA(?TK_META_NS_APIKEYMGMT, SubjectID),
metadata = #{?META_PARTY_ID := SubjectID},
authority = ?TK_AUTHORITY_KEYCLOAK
} = call_get_by_token(Token, ?TOKEN_SOURCE_CONTEXT(), Client),
_ = assert_context({api_key_token, JTI, SubjectID}, Context).
@ -357,7 +372,11 @@ detect_user_session_token_test(C) ->
token = Token,
status = active,
context = Context,
metadata = ?USER_METADATA(?TK_META_NS_KEYCLOAK, SubjectID, SubjectEmail),
metadata = #{
?META_USER_ID := SubjectID,
?META_USER_EMAIL := SubjectEmail,
?META_USER_REALM := <<"external">>
},
authority = ?TK_AUTHORITY_KEYCLOAK
} = call_get_by_token(Token, ?TOKEN_SOURCE_CONTEXT(?USER_TOKEN_SOURCE), Client),
_ = assert_context({user_session_token, JTI, SubjectID, SubjectEmail, unlimited}, Context).
@ -389,7 +408,7 @@ bouncer_context_from_claims_test(C) ->
token = Token,
status = active,
context = Context,
metadata = ?PARTY_METADATA(?TK_META_NS_APIKEYMGMT, SubjectID),
metadata = #{?META_PARTY_ID := SubjectID},
authority = ?TK_AUTHORITY_CAPI
} = call_get_by_token(Token, ?TOKEN_SOURCE_CONTEXT(), Client),
_ = assert_context({claim_token, JTI}, Context).
@ -405,7 +424,7 @@ cons_claim_passthrough_test(C) ->
token = Token,
status = active,
context = Context,
metadata = ?METADATA(?TK_META_NS_APIKEYMGMT, #{<<"party_id">> := SubjectID, <<"cons">> := <<"client">>}),
metadata = #{?META_PARTY_ID := SubjectID, ?META_CAPI_CONSUMER := <<"client">>},
authority = ?TK_AUTHORITY_CAPI
} = call_get_by_token(Token, ?TOKEN_SOURCE_CONTEXT(), Client),
_ = assert_context({claim_token, JTI}, Context).
@ -436,7 +455,7 @@ invoice_template_access_token_ok_test(C) ->
token = Token,
status = active,
context = Context,
metadata = ?PARTY_METADATA(?TK_META_NS_APIKEYMGMT, SubjectID),
metadata = #{?META_PARTY_ID := SubjectID},
authority = ?TK_AUTHORITY_CAPI
} = call_get_by_token(Token, ?TOKEN_SOURCE_CONTEXT(), Client),
_ = assert_context({invoice_template_access_token, JTI, SubjectID, InvoiceTemplateID}, Context).
@ -482,7 +501,7 @@ basic_issuing_test(C) ->
type = v1_thrift_binary,
content = BinaryContextFragment
},
Metadata = #{<<"ns">> => #{<<"my">> => <<"metadata">>}},
Metadata = #{<<"my">> => <<"metadata">>},
#token_keeper_AuthData{
id = undefined,
token = Token,