From b44252fde97e2b9ebbee4c568e023d4f3d96acf3 Mon Sep 17 00:00:00 2001 From: Clemens Zagler Date: Tue, 12 Mar 2024 13:25:21 +0100 Subject: [PATCH] authz/client: Fix getPermissions returning wrong type Due to an issue with runtime type erasure, getPermissions returned a List instead of List. Fixed and added test to catch this Closes #16520 Signed-off-by: Clemens Zagler --- .../client/resource/AuthorizationResource.java | 15 +++++---------- .../release_notes/topics/25_0_0.adoc | 8 ++++++++ .../testsuite/authz/AuthorizationAPITest.java | 1 + .../keycloak/testsuite/authz/RegexPolicyTest.java | 7 ++----- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/authz/client/src/main/java/org/keycloak/authorization/client/resource/AuthorizationResource.java b/authz/client/src/main/java/org/keycloak/authorization/client/resource/AuthorizationResource.java index 0a2887f0bb..c613b4855a 100644 --- a/authz/client/src/main/java/org/keycloak/authorization/client/resource/AuthorizationResource.java +++ b/authz/client/src/main/java/org/keycloak/authorization/client/resource/AuthorizationResource.java @@ -71,7 +71,7 @@ public class AuthorizationResource { * @throws AuthorizationDeniedException in case the request was denied by the server */ public AuthorizationResponse authorize(final AuthorizationRequest request) throws AuthorizationDeniedException { - return invoke(request); + return invoke(request, new TypeReference(){}); } /** @@ -93,10 +93,10 @@ public class AuthorizationResource { metadata.setResponseMode("permissions"); - return invoke(request); + return (List) invoke(request, new TypeReference>(){}); } - private T invoke(AuthorizationRequest request) { + private T invoke(AuthorizationRequest request, TypeReference responseType) { if (request == null) { throw new IllegalArgumentException("Authorization request must not be null"); } @@ -117,13 +117,8 @@ public class AuthorizationResource { HttpMethodResponse response = method .authentication() .uma(request) - .response(); - - if (request.getMetadata() != null && "permissions".equals(request.getMetadata().getResponseMode())) { - response = response.json(new TypeReference(){}); - } else { - response = response.json((Class) AuthorizationResponse.class); - } + .response() + .json(responseType); return response.execute(); } diff --git a/docs/documentation/release_notes/topics/25_0_0.adoc b/docs/documentation/release_notes/topics/25_0_0.adoc index 0b6773367a..622abd246e 100644 --- a/docs/documentation/release_notes/topics/25_0_0.adoc +++ b/docs/documentation/release_notes/topics/25_0_0.adoc @@ -26,3 +26,11 @@ Keycloak supports a new password policy that allows you to deny user passwords w = Searching by user attribute no longer case insensitive When searching for users by user attribute, {project_name} no longer searches for user attribute names forcing lower case comparisons. The goal of this change was to speed up searches by using {project_name}'s native index on the user attribute table. If your database collation is case-insensitive, your search results will stay the same. If your database collation is case-sensitive, you might see less search results than before. + += Breaking fix in authorization client library + +For users of the `keycloak-authz-client` library, calling `AuthorizationResource.getPermissions(...)` now correctly returns a `List`. + +Previously, it would return a `List` at runtime, even though the method declaration advertised `List`. + +This fix will break code that relied on casting the List or its contents to `List`. If you have used this method in any capacity, you are likely to have done this and be affected. \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthorizationAPITest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthorizationAPITest.java index b1ad3c1e03..ff16398bab 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthorizationAPITest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthorizationAPITest.java @@ -204,6 +204,7 @@ public class AuthorizationAPITest extends AbstractAuthzTest { List permissions = authzClient.authorization("marta", "password").getPermissions(request); assertFalse(permissions.isEmpty()); + assertTrue(permissions.get(0) instanceof Permission); } public void testResourceServerAsAudience(String clientId, String resourceServerClientId, String authzConfigFile) throws Exception { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/RegexPolicyTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/RegexPolicyTest.java index 467d944d9e..56a6f93914 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/RegexPolicyTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/RegexPolicyTest.java @@ -290,11 +290,8 @@ private void createRegexPolicyExtended(String name, String targetClaim, String p theRequest.setMetadata(metadata); List permissions = authzClient.authorization("admin", "password").getPermissions(theRequest); assertNotNull(permissions); - Assert.assertTrue(((Map)permissions.get(0)).get("rsname").equals("service")); - Assert.assertTrue(((List)(((Map)permissions.get(0)).get("scopes"))).get(0).equals("read")); - - - + Assert.assertTrue(permissions.get(0).getResourceName().equals("service")); + Assert.assertTrue(permissions.get(0).getScopes().contains("read")); }