Skip to content

Commit

Permalink
Make scopes optional for oauth2 authentication
Browse files Browse the repository at this point in the history
(cherry picked from commit 84e8d17)
  • Loading branch information
MarcialRosales authored and mergify[bot] committed May 30, 2023
1 parent 2f071b8 commit f26358c
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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, <<ResourceServerId/binary, ".">>),
Expand All @@ -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}}};
Expand Down Expand Up @@ -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}) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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([]).

Expand Down
2 changes: 1 addition & 1 deletion deps/rabbitmq_auth_backend_oauth2/test/scope_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ all() ->
permission_resource,
permission_topic
].

variable_expansion(_Config) ->
Scenarios = [
{ "Emtpy Scopes",
Expand Down
49 changes: 49 additions & 0 deletions deps/rabbitmq_auth_backend_oauth2/test/unit_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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">>),
Expand Down Expand Up @@ -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">>,
Expand Down

0 comments on commit f26358c

Please sign in to comment.