Merge pull request #8412 from rabbitmq/fix-8391
Make scopes optional for oauth2 authentication
This commit is contained in:
commit
bcc2bc8525
|
@ -496,7 +496,7 @@ post_process_payload_in_rich_auth_request_format(#{<<"authorization_details">> :
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
validate_payload(#{?SCOPE_JWT_FIELD := _Scope } = DecodedToken) ->
|
validate_payload(DecodedToken) ->
|
||||||
ResourceServerEnv = application:get_env(?APP, ?RESOURCE_SERVER_ID, <<>>),
|
ResourceServerEnv = application:get_env(?APP, ?RESOURCE_SERVER_ID, <<>>),
|
||||||
ResourceServerId = rabbit_data_coercion:to_binary(ResourceServerEnv),
|
ResourceServerId = rabbit_data_coercion:to_binary(ResourceServerEnv),
|
||||||
ScopePrefix = application:get_env(?APP, ?SCOPE_PREFIX, <<ResourceServerId/binary, ".">>),
|
ScopePrefix = application:get_env(?APP, ?SCOPE_PREFIX, <<ResourceServerId/binary, ".">>),
|
||||||
|
@ -507,6 +507,11 @@ validate_payload(#{?SCOPE_JWT_FIELD := Scope, ?AUD_JWT_FIELD := Aud} = DecodedTo
|
||||||
ok -> {ok, DecodedToken#{?SCOPE_JWT_FIELD => filter_scopes(Scope, ScopePrefix)}};
|
ok -> {ok, DecodedToken#{?SCOPE_JWT_FIELD => filter_scopes(Scope, ScopePrefix)}};
|
||||||
{error, Err} -> {refused, {invalid_aud, Err}}
|
{error, Err} -> {refused, {invalid_aud, Err}}
|
||||||
end;
|
end;
|
||||||
|
validate_payload(#{?AUD_JWT_FIELD := Aud} = DecodedToken, ResourceServerId, _ScopePrefix) ->
|
||||||
|
case check_aud(Aud, ResourceServerId) of
|
||||||
|
ok -> {ok, DecodedToken};
|
||||||
|
{error, Err} -> {refused, {invalid_aud, Err}}
|
||||||
|
end;
|
||||||
validate_payload(#{?SCOPE_JWT_FIELD := Scope} = DecodedToken, _ResourceServerId, ScopePrefix) ->
|
validate_payload(#{?SCOPE_JWT_FIELD := Scope} = DecodedToken, _ResourceServerId, ScopePrefix) ->
|
||||||
case application:get_env(?APP, ?VERIFY_AUD, true) of
|
case application:get_env(?APP, ?VERIFY_AUD, true) of
|
||||||
true -> {error, {badarg, {aud_field_is_missing}}};
|
true -> {error, {badarg, {aud_field_is_missing}}};
|
||||||
|
@ -534,7 +539,8 @@ check_aud(Aud, ResourceServerId) ->
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
get_scopes(#{?SCOPE_JWT_FIELD := Scope}) -> Scope.
|
get_scopes(#{?SCOPE_JWT_FIELD := Scope}) -> Scope;
|
||||||
|
get_scopes(#{}) -> [].
|
||||||
|
|
||||||
-spec get_expanded_scopes(map(), #resource{}) -> [binary()].
|
-spec get_expanded_scopes(map(), #resource{}) -> [binary()].
|
||||||
get_expanded_scopes(Token, #resource{virtual_host = VHost}) ->
|
get_expanded_scopes(Token, #resource{virtual_host = VHost}) ->
|
||||||
|
|
|
@ -84,6 +84,15 @@ token_with_scopes_and_expiration(Scopes, Expiration) ->
|
||||||
<<"aud">> => [<<"rabbitmq">>],
|
<<"aud">> => [<<"rabbitmq">>],
|
||||||
<<"scope">> => Scopes}.
|
<<"scope">> => Scopes}.
|
||||||
|
|
||||||
|
token_without_scopes() ->
|
||||||
|
%% expiration is a timestamp with precision in seconds
|
||||||
|
#{
|
||||||
|
<<"kid">> => <<"token-key">>,
|
||||||
|
<<"iss">> => <<"unit_test">>,
|
||||||
|
<<"foo">> => <<"bar">>,
|
||||||
|
<<"aud">> => [<<"rabbitmq">>]
|
||||||
|
}.
|
||||||
|
|
||||||
fixture_token() ->
|
fixture_token() ->
|
||||||
fixture_token([]).
|
fixture_token([]).
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ all() ->
|
||||||
permission_resource,
|
permission_resource,
|
||||||
permission_topic
|
permission_topic
|
||||||
].
|
].
|
||||||
|
|
||||||
variable_expansion(_Config) ->
|
variable_expansion(_Config) ->
|
||||||
Scenarios = [
|
Scenarios = [
|
||||||
{ "Emtpy Scopes",
|
{ "Emtpy Scopes",
|
||||||
|
|
|
@ -19,8 +19,12 @@ all() ->
|
||||||
test_validate_payload_resource_server_id_mismatch,
|
test_validate_payload_resource_server_id_mismatch,
|
||||||
test_validate_payload_with_scope_prefix,
|
test_validate_payload_with_scope_prefix,
|
||||||
test_validate_payload,
|
test_validate_payload,
|
||||||
|
test_validate_payload_without_scope,
|
||||||
test_validate_payload_when_verify_aud_false,
|
test_validate_payload_when_verify_aud_false,
|
||||||
test_successful_access_with_a_token,
|
test_successful_access_with_a_token,
|
||||||
|
test_successful_authentication_without_scopes,
|
||||||
|
test_successful_authorization_without_scopes,
|
||||||
|
test_unsuccessful_access_without_scopes,
|
||||||
test_successful_access_with_a_token_with_variables_in_scopes,
|
test_successful_access_with_a_token_with_variables_in_scopes,
|
||||||
test_successful_access_with_a_parsed_token,
|
test_successful_access_with_a_parsed_token,
|
||||||
test_successful_access_with_a_token_that_has_tag_scopes,
|
test_successful_access_with_a_token_that_has_tag_scopes,
|
||||||
|
@ -609,6 +613,30 @@ post_process_payload_with_complex_claim_authorization(Authorization) ->
|
||||||
{true, Payload} = uaa_jwt_jwt:decode_and_verify(Jwk, EncodedToken),
|
{true, Payload} = uaa_jwt_jwt:decode_and_verify(Jwk, EncodedToken),
|
||||||
rabbit_auth_backend_oauth2:post_process_payload(Payload).
|
rabbit_auth_backend_oauth2:post_process_payload(Payload).
|
||||||
|
|
||||||
|
test_successful_authentication_without_scopes(_) ->
|
||||||
|
Jwk = ?UTIL_MOD:fixture_jwk(),
|
||||||
|
UaaEnv = [{signing_keys, #{<<"token-key">> => {map, Jwk}}}],
|
||||||
|
application:set_env(rabbitmq_auth_backend_oauth2, key_config, UaaEnv),
|
||||||
|
application:set_env(rabbitmq_auth_backend_oauth2, resource_server_id, <<"rabbitmq">>),
|
||||||
|
|
||||||
|
Username = <<"username">>,
|
||||||
|
Token = ?UTIL_MOD:sign_token_hs(?UTIL_MOD:token_with_sub(?UTIL_MOD:fixture_token(), Username), Jwk),
|
||||||
|
|
||||||
|
{ok, #auth_user{username = Username} } =
|
||||||
|
rabbit_auth_backend_oauth2:user_login_authentication(Username, [{password, Token}]).
|
||||||
|
|
||||||
|
test_successful_authorization_without_scopes(_) ->
|
||||||
|
Jwk = ?UTIL_MOD:fixture_jwk(),
|
||||||
|
UaaEnv = [{signing_keys, #{<<"token-key">> => {map, Jwk}}}],
|
||||||
|
application:set_env(rabbitmq_auth_backend_oauth2, key_config, UaaEnv),
|
||||||
|
application:set_env(rabbitmq_auth_backend_oauth2, resource_server_id, <<"rabbitmq">>),
|
||||||
|
|
||||||
|
Username = <<"username">>,
|
||||||
|
Token = ?UTIL_MOD:sign_token_hs(?UTIL_MOD:token_with_sub(?UTIL_MOD:fixture_token(), Username), Jwk),
|
||||||
|
|
||||||
|
{ok, _ } =
|
||||||
|
rabbit_auth_backend_oauth2:user_login_authorization(Username, [{password, Token}]).
|
||||||
|
|
||||||
test_successful_access_with_a_token(_) ->
|
test_successful_access_with_a_token(_) ->
|
||||||
%% Generate a token with JOSE
|
%% Generate a token with JOSE
|
||||||
%% Check authorization with the token
|
%% Check authorization with the token
|
||||||
|
@ -980,6 +1008,21 @@ test_unsuccessful_access_with_a_bogus_token(_) ->
|
||||||
?assertMatch({refused, _, _},
|
?assertMatch({refused, _, _},
|
||||||
rabbit_auth_backend_oauth2:user_login_authentication(Username, [{password, <<"not a token">>}])).
|
rabbit_auth_backend_oauth2:user_login_authentication(Username, [{password, <<"not a token">>}])).
|
||||||
|
|
||||||
|
test_unsuccessful_access_without_scopes(_) ->
|
||||||
|
Username = <<"username">>,
|
||||||
|
application:set_env(rabbitmq_auth_backend_oauth2, resource_server_id, <<"rabbitmq">>),
|
||||||
|
|
||||||
|
Jwk = ?UTIL_MOD:fixture_jwk(),
|
||||||
|
Token = ?UTIL_MOD:sign_token_hs(?UTIL_MOD:token_with_sub(?UTIL_MOD:token_without_scopes(), Username), Jwk),
|
||||||
|
UaaEnv = [{signing_keys, #{<<"token-key">> => {map, Jwk}}}],
|
||||||
|
application:set_env(rabbitmq_auth_backend_oauth2, key_config, UaaEnv),
|
||||||
|
|
||||||
|
{ok, #auth_user{username = Username, tags = [], impl = CredentialsFun } = AuthUser} =
|
||||||
|
rabbit_auth_backend_oauth2:user_login_authentication(Username, [{password, Token}]),
|
||||||
|
|
||||||
|
ct:log("authuser ~p ~p ", [AuthUser, CredentialsFun()]),
|
||||||
|
assert_vhost_access_denied(AuthUser, <<"vhost">>).
|
||||||
|
|
||||||
test_restricted_vhost_access_with_a_valid_token(_) ->
|
test_restricted_vhost_access_with_a_valid_token(_) ->
|
||||||
Username = <<"username">>,
|
Username = <<"username">>,
|
||||||
application:set_env(rabbitmq_auth_backend_oauth2, resource_server_id, <<"rabbitmq">>),
|
application:set_env(rabbitmq_auth_backend_oauth2, resource_server_id, <<"rabbitmq">>),
|
||||||
|
@ -1277,6 +1320,12 @@ test_validate_payload(_) ->
|
||||||
<<"scope">> => [<<"bar">>, <<"other.third">>]}},
|
<<"scope">> => [<<"bar">>, <<"other.third">>]}},
|
||||||
rabbit_auth_backend_oauth2:validate_payload(KnownResourceServerId, ?RESOURCE_SERVER_ID, ?DEFAULT_SCOPE_PREFIX)).
|
rabbit_auth_backend_oauth2:validate_payload(KnownResourceServerId, ?RESOURCE_SERVER_ID, ?DEFAULT_SCOPE_PREFIX)).
|
||||||
|
|
||||||
|
test_validate_payload_without_scope(_) ->
|
||||||
|
KnownResourceServerId = #{<<"aud">> => [?RESOURCE_SERVER_ID]
|
||||||
|
},
|
||||||
|
?assertEqual({ok, #{<<"aud">> => [?RESOURCE_SERVER_ID] }},
|
||||||
|
rabbit_auth_backend_oauth2:validate_payload(KnownResourceServerId, ?RESOURCE_SERVER_ID, ?DEFAULT_SCOPE_PREFIX)).
|
||||||
|
|
||||||
test_validate_payload_when_verify_aud_false(_) ->
|
test_validate_payload_when_verify_aud_false(_) ->
|
||||||
WithoutAud = #{
|
WithoutAud = #{
|
||||||
<<"scope">> => [<<"foo">>, <<"rabbitmq.bar">>,
|
<<"scope">> => [<<"foo">>, <<"rabbitmq.bar">>,
|
||||||
|
|
Loading…
Reference in New Issue