diff --git a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl index eea7771782..8c839e9257 100644 --- a/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl +++ b/deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl @@ -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, <<>>), ResourceServerId = rabbit_data_coercion:to_binary(ResourceServerEnv), ScopePrefix = application:get_env(?APP, ?SCOPE_PREFIX, <>), @@ -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)}}; {error, Err} -> {refused, {invalid_aud, Err}} 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) -> case application:get_env(?APP, ?VERIFY_AUD, true) of 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()]. get_expanded_scopes(Token, #resource{virtual_host = VHost}) -> diff --git a/deps/rabbitmq_auth_backend_oauth2/test/rabbit_auth_backend_oauth2_test_util.erl b/deps/rabbitmq_auth_backend_oauth2/test/rabbit_auth_backend_oauth2_test_util.erl index 51d0a94355..715806179b 100644 --- a/deps/rabbitmq_auth_backend_oauth2/test/rabbit_auth_backend_oauth2_test_util.erl +++ b/deps/rabbitmq_auth_backend_oauth2/test/rabbit_auth_backend_oauth2_test_util.erl @@ -84,6 +84,15 @@ token_with_scopes_and_expiration(Scopes, Expiration) -> <<"aud">> => [<<"rabbitmq">>], <<"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([]). diff --git a/deps/rabbitmq_auth_backend_oauth2/test/scope_SUITE.erl b/deps/rabbitmq_auth_backend_oauth2/test/scope_SUITE.erl index 73062ce08b..65964871a5 100644 --- a/deps/rabbitmq_auth_backend_oauth2/test/scope_SUITE.erl +++ b/deps/rabbitmq_auth_backend_oauth2/test/scope_SUITE.erl @@ -20,7 +20,7 @@ all() -> permission_resource, permission_topic ]. - + variable_expansion(_Config) -> Scenarios = [ { "Emtpy Scopes", diff --git a/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl b/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl index 71b74590bb..8395909dbd 100644 --- a/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl +++ b/deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl @@ -19,8 +19,12 @@ all() -> test_validate_payload_resource_server_id_mismatch, test_validate_payload_with_scope_prefix, test_validate_payload, + test_validate_payload_without_scope, test_validate_payload_when_verify_aud_false, 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_parsed_token, 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), 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(_) -> %% Generate a token with JOSE %% Check authorization with the token @@ -980,6 +1008,21 @@ test_unsuccessful_access_with_a_bogus_token(_) -> ?assertMatch({refused, _, _}, 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(_) -> Username = <<"username">>, application:set_env(rabbitmq_auth_backend_oauth2, resource_server_id, <<"rabbitmq">>), @@ -1277,6 +1320,12 @@ test_validate_payload(_) -> <<"scope">> => [<<"bar">>, <<"other.third">>]}}, 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(_) -> WithoutAud = #{ <<"scope">> => [<<"foo">>, <<"rabbitmq.bar">>,