From 19956203a861343e8f104f71ceac8110a400a0e2 Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish <62088117+mdanish98@users.noreply.github.com> Date: Mon, 28 Oct 2024 16:22:46 +0100 Subject: [PATCH] Fixes resource roles consideration (#501) * Enhancements on Role provider to also consider resource_roles Signed-off-by: Mohammad Ghazanfar Ali Danish * Addresses review remarks Signed-off-by: Mohammad Ghazanfar Ali Danish * Improves formatting Signed-off-by: Mohammad Ghazanfar Ali Danish * Fixes the resource roles consideration Signed-off-by: Mohammad Ghazanfar Ali Danish * Changes the Datastructure to make compatible Signed-off-by: Mohammad Ghazanfar Ali Danish * Fixes tests Signed-off-by: Mohammad Ghazanfar Ali Danish * Refactors test Signed-off-by: Mohammad Ghazanfar Ali Danish * Improves formatting Signed-off-by: Mohammad Ghazanfar Ali Danish * Addresses review remarks Signed-off-by: Mohammad Ghazanfar Ali Danish * Adjust rules Signed-off-by: Mohammad Ghazanfar Ali Danish * Removes warnings Signed-off-by: Mohammad Ghazanfar Ali Danish --------- Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../TestAuthorizedAasRepository.java | 30 +++ .../src/test/resources/rbac_rules.json | 24 +++ .../rbac/KeycloakRoleProvider.java | 41 ++-- .../TestKeycloakRoleProvider.java | 197 +++++++++--------- ci/keycloak/realm/BaSyx-realm.json | 49 +++-- 5 files changed, 201 insertions(+), 140 deletions(-) diff --git a/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/TestAuthorizedAasRepository.java b/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/TestAuthorizedAasRepository.java index 76d503397..83c561788 100644 --- a/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/TestAuthorizedAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/TestAuthorizedAasRepository.java @@ -150,6 +150,26 @@ public void getAasWithCorrectRoleAndPermission() throws IOException { assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode()); } + @Test + public void getAasWithOnlyResourceRole() throws IOException { + DummyCredential dummyCredential = DummyCredentialStore.USER_CREDENTIAL; + + String accessToken = tokenProvider.getAccessToken(dummyCredential.getUsername(), dummyCredential.getPassword()); + + CloseableHttpResponse retrievalResponse = getElementWithAuthorization(getSpecificAasAccessURL(SPECIFIC_SHELL_ID), accessToken); + assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode()); + } + + @Test + public void getAasWithBothRealmAndResourceRole() throws IOException { + DummyCredential dummyCredential = DummyCredentialStore.VISITOR_CREDENTIAL; + + String accessToken = tokenProvider.getAccessToken(dummyCredential.getUsername(), dummyCredential.getPassword()); + + CloseableHttpResponse retrievalResponse = getElementWithAuthorization(getSpecificAasAccessURL(SPECIFIC_SHELL_ID), accessToken); + assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode()); + } + @Test public void getAasWithCorrectRoleAndSpecificAasPermission() throws IOException { DummyCredential dummyCredential = DummyCredentialStore.BASYX_READER_TWO_CREDENTIAL; @@ -196,6 +216,16 @@ public void createAasWithCorrectRoleAndPermission() throws IOException { deleteElementWithAuthorization(getSpecificAasAccessURL(SPECIFIC_SHELL_ID_2), getAccessToken(DummyCredentialStore.ADMIN_CREDENTIAL)); } + @Test + public void createAasWithBothRealmAndResourceRole() throws IOException { + String accessToken = getAccessToken(DummyCredentialStore.VISITOR_CREDENTIAL); + + CloseableHttpResponse retrievalResponse = createAasOnRepositoryWithAuthorization(getAasJSONString(AAS_SIMPLE_2_JSON), accessToken); + assertEquals(HttpStatus.CREATED.value(), retrievalResponse.getCode()); + + deleteElementWithAuthorization(getSpecificAasAccessURL(SPECIFIC_SHELL_ID_2), getAccessToken(DummyCredentialStore.ADMIN_CREDENTIAL)); + } + @Test public void createAasWithInsufficientPermissionRole() throws IOException { String accessToken = getAccessToken(DummyCredentialStore.BASYX_READER_CREDENTIAL); diff --git a/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/test/resources/rbac_rules.json b/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/test/resources/rbac_rules.json index 6bf880c8d..4dc81114d 100644 --- a/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/test/resources/rbac_rules.json +++ b/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/test/resources/rbac_rules.json @@ -15,6 +15,30 @@ "aasIds": "*" } }, + { + "role": "basyx-user", + "action": "READ", + "targetInformation": { + "@type": "aas", + "aasIds": "specificAasId" + } + }, + { + "role": "basyx-user", + "action": "CREATE", + "targetInformation": { + "@type": "aas", + "aasIds": "specificAasId-2" + } + }, + { + "role": "visitor", + "action": "READ", + "targetInformation": { + "@type": "aas", + "aasIds": "specificAasId" + } + }, { "role": "basyx-reader-two", "action": "READ", diff --git a/basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/KeycloakRoleProvider.java b/basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/KeycloakRoleProvider.java index 03f1c672f..6a0a8088c 100644 --- a/basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/KeycloakRoleProvider.java +++ b/basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/KeycloakRoleProvider.java @@ -30,6 +30,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.eclipse.digitaltwin.basyx.authorization.CommonAuthorizationProperties; import org.eclipse.digitaltwin.basyx.authorization.SubjectInformation; @@ -68,7 +69,7 @@ public List getRoles() { validateJwt(jwt); Map> realmAccess = new HashMap<>(); - Map> resourceAccess = new HashMap<>(); + Map>> resourceAccess = new HashMap<>(); if (jwt.hasClaim(CLAIM_REALM_ACCESS)) realmAccess = jwt.getClaim(CLAIM_REALM_ACCESS); @@ -79,32 +80,26 @@ public List getRoles() { return extractRolesFromClaims(realmAccess, resourceAccess); } - private List extractRolesFromClaims(Map> realmAccess, Map> resourceAccess) { + private List extractRolesFromClaims(Map> realmAccess, Map>> resourceAccess) { if (realmAccess.isEmpty() && resourceAccess.isEmpty()) return new ArrayList<>(); - Collection realmRoles = realmAccess.get(CLAIM_ROLES); - Collection resourceRoles = resourceAccess.get(CLAIM_ROLES); - - if ((realmRoles == null || realmRoles.isEmpty()) && (resourceRoles == null || resourceRoles.isEmpty())) - return new ArrayList<>(); - - return mergeRoles(realmRoles, resourceRoles); - } - - private List mergeRoles(Collection realmRoles, Collection resourceRoles) { - - if (realmRoles == null || realmRoles.isEmpty()) - return new ArrayList<>(resourceRoles); - - if (resourceRoles == null || resourceRoles.isEmpty()) - return new ArrayList<>(realmRoles); + List roles = new ArrayList<>(); - List rolesUnion = new ArrayList<>(realmRoles); + Collection realmRoles = realmAccess.get(CLAIM_ROLES); - resourceRoles.stream().filter(resourceRole -> !rolesUnion.contains(resourceRole)).forEach(rolesUnion::add); - - return rolesUnion; + if (realmRoles != null && !realmRoles.isEmpty()) + roles.addAll(realmRoles); + + for (Map.Entry>> entry : resourceAccess.entrySet()) { + Map> clientRolesMap = entry.getValue(); + Collection clientRoles = clientRolesMap.get(CLAIM_ROLES); + + if (clientRoles != null) + roles.addAll(clientRoles); + } + + return roles.stream().distinct().collect(Collectors.toList()); } private void validateJwt(Jwt jwt) { @@ -121,4 +116,4 @@ private SubjectInformation getSubjectInformation() { return subjectInfo; } -} +} \ No newline at end of file diff --git a/basyx.common/basyx.authorization/src/test/java/org/eclipse/digitaltwin/basyx/authorization/TestKeycloakRoleProvider.java b/basyx.common/basyx.authorization/src/test/java/org/eclipse/digitaltwin/basyx/authorization/TestKeycloakRoleProvider.java index 4d2e2328b..3b5756232 100644 --- a/basyx.common/basyx.authorization/src/test/java/org/eclipse/digitaltwin/basyx/authorization/TestKeycloakRoleProvider.java +++ b/basyx.common/basyx.authorization/src/test/java/org/eclipse/digitaltwin/basyx/authorization/TestKeycloakRoleProvider.java @@ -47,143 +47,142 @@ public class TestKeycloakRoleProvider { @Mock - private SubjectInformationProvider subjectInformationProvider; + private SubjectInformationProvider subjectInformationProvider; @Mock - private Jwt jwt; + private Jwt jwt; @InjectMocks - private KeycloakRoleProvider keycloakRoleProvider; + private KeycloakRoleProvider keycloakRoleProvider; @Before - public void setUp() { - MockitoAnnotations.openMocks(this); + public void setUp() { + MockitoAnnotations.openMocks(this); - @SuppressWarnings("unchecked") - SubjectInformation subjectInfo = mock(SubjectInformation.class); - when(subjectInfo.get()).thenReturn(jwt); - when(subjectInformationProvider.get()).thenReturn(subjectInfo); - } + @SuppressWarnings("unchecked") + SubjectInformation subjectInfo = mock(SubjectInformation.class); + when(subjectInfo.get()).thenReturn(jwt); + when(subjectInformationProvider.get()).thenReturn(subjectInfo); + } @Test - public void getRoles_whenBothRealmAndResourceRolesPresent() { - Map> realmAccess = new HashMap<>(); - realmAccess.put("roles", Arrays.asList("ROLE_USER", "ROLE_ADMIN")); + public void getRoles_whenBothRealmAndResourceRolesPresent() { + Map> realmAccess = new HashMap<>(); + realmAccess.put("roles", Arrays.asList("ROLE_USER", "ROLE_ADMIN")); - Map> resourceAccess = new HashMap<>(); - resourceAccess.put("roles", Arrays.asList("ROLE_SUPERUSER", "ROLE_ADMIN")); + Map>> resourceAccess = new HashMap<>(); + resourceAccess.put("client1", new HashMap<>(Collections.singletonMap("roles", Arrays.asList("ROLE_SUPERUSER", "ROLE_ADMIN")))); + resourceAccess.put("client2", new HashMap<>(Collections.singletonMap("roles", Arrays.asList("ROLE_SUPPORT")))); - when(jwt.hasClaim("realm_access")).thenReturn(true); - when(jwt.hasClaim("resource_access")).thenReturn(true); - when(jwt.getClaim("realm_access")).thenReturn(realmAccess); - when(jwt.getClaim("resource_access")).thenReturn(resourceAccess); + when(jwt.hasClaim("realm_access")).thenReturn(true); + when(jwt.hasClaim("resource_access")).thenReturn(true); + when(jwt.getClaim("realm_access")).thenReturn(realmAccess); + when(jwt.getClaim("resource_access")).thenReturn(resourceAccess); - List roles = keycloakRoleProvider.getRoles(); + List roles = keycloakRoleProvider.getRoles(); - assertEquals(3, roles.size()); - assertTrue(roles.contains("ROLE_USER")); - assertTrue(roles.contains("ROLE_ADMIN")); - assertTrue(roles.contains("ROLE_SUPERUSER")); - } + assertEquals(4, roles.size()); + assertTrue(roles.contains("ROLE_USER")); + assertTrue(roles.contains("ROLE_ADMIN")); + assertTrue(roles.contains("ROLE_SUPERUSER")); + assertTrue(roles.contains("ROLE_SUPPORT")); + } @Test - public void getRoles_whenOnlyRealmRolesPresent() { - Map> realmAccess = new HashMap<>(); - realmAccess.put("roles", Arrays.asList("ROLE_USER", "ROLE_ADMIN")); + public void getRoles_whenOnlyRealmRolesPresent() { + Map> realmAccess = new HashMap<>(); + realmAccess.put("roles", Arrays.asList("ROLE_USER", "ROLE_ADMIN")); - when(jwt.hasClaim("realm_access")).thenReturn(true); - when(jwt.hasClaim("resource_access")).thenReturn(true); - when(jwt.getClaim("realm_access")).thenReturn(realmAccess); - when(jwt.getClaim("resource_access")).thenReturn(Collections.emptyMap()); + when(jwt.hasClaim("realm_access")).thenReturn(true); + when(jwt.hasClaim("resource_access")).thenReturn(true); + when(jwt.getClaim("realm_access")).thenReturn(realmAccess); + when(jwt.getClaim("resource_access")).thenReturn(Collections.emptyMap()); - List roles = keycloakRoleProvider.getRoles(); + List roles = keycloakRoleProvider.getRoles(); - assertEquals(2, roles.size()); - assertTrue(roles.contains("ROLE_USER")); - assertTrue(roles.contains("ROLE_ADMIN")); - } + assertEquals(2, roles.size()); + assertTrue(roles.contains("ROLE_USER")); + assertTrue(roles.contains("ROLE_ADMIN")); + } @Test - public void getRoles_whenOnlyResourceRolesPresent() { - Map> resourceAccess = new HashMap<>(); - resourceAccess.put("roles", Arrays.asList("ROLE_SUPERUSER", "ROLE_SUPPORT")); + public void getRoles_whenOnlyResourceRolesPresent() { + Map>> resourceAccess = new HashMap<>(); + resourceAccess.put("client1", new HashMap<>(Collections.singletonMap("roles", Arrays.asList("ROLE_SUPERUSER", "ROLE_SUPPORT")))); - when(jwt.hasClaim("realm_access")).thenReturn(true); - when(jwt.hasClaim("resource_access")).thenReturn(true); - when(jwt.getClaim("realm_access")).thenReturn(Collections.emptyMap()); - when(jwt.getClaim("resource_access")).thenReturn(resourceAccess); + when(jwt.hasClaim("realm_access")).thenReturn(true); + when(jwt.hasClaim("resource_access")).thenReturn(true); + when(jwt.getClaim("realm_access")).thenReturn(Collections.emptyMap()); + when(jwt.getClaim("resource_access")).thenReturn(resourceAccess); - List roles = keycloakRoleProvider.getRoles(); + List roles = keycloakRoleProvider.getRoles(); - assertEquals(2, roles.size()); - assertTrue(roles.contains("ROLE_SUPERUSER")); - assertTrue(roles.contains("ROLE_SUPPORT")); - } + assertEquals(2, roles.size()); + assertTrue(roles.contains("ROLE_SUPERUSER")); + assertTrue(roles.contains("ROLE_SUPPORT")); + } @Test - public void getRoles_whenNoRolesPresent() { - when(jwt.hasClaim("realm_access")).thenReturn(true); - when(jwt.hasClaim("resource_access")).thenReturn(true); - when(jwt.getClaim("realm_access")).thenReturn(Collections.emptyMap()); - when(jwt.getClaim("resource_access")).thenReturn(Collections.emptyMap()); - - List roles = keycloakRoleProvider.getRoles(); - - assertTrue(roles.isEmpty()); - } + public void getRoles_whenNoRolesPresent() { + when(jwt.hasClaim("realm_access")).thenReturn(true); + when(jwt.hasClaim("resource_access")).thenReturn(true); + when(jwt.getClaim("realm_access")).thenReturn(Collections.emptyMap()); + when(jwt.getClaim("resource_access")).thenReturn(Collections.emptyMap()); - @Test(expected = NullSubjectException.class) - public void getRoles_whenJwtIsNull() { + List roles = keycloakRoleProvider.getRoles(); - @SuppressWarnings("unchecked") - SubjectInformation subjectInfo = mock(SubjectInformation.class); - when(subjectInfo.get()).thenReturn(null); - when(subjectInformationProvider.get()).thenReturn(subjectInfo); + assertTrue(roles.isEmpty()); + } - keycloakRoleProvider.getRoles(); - } + @Test(expected = NullSubjectException.class) + public void getRoles_whenJwtIsNull() { + @SuppressWarnings("unchecked") + SubjectInformation subjectInfo = mock(SubjectInformation.class); + when(subjectInfo.get()).thenReturn(null); + when(subjectInformationProvider.get()).thenReturn(subjectInfo); - @Test - public void getRoles_whenRealmAccessNotPresentButResourceAccessPresent() { - Map> resourceAccess = new HashMap<>(); - resourceAccess.put("roles", Arrays.asList("ROLE_SUPPORT", "ROLE_USER")); + keycloakRoleProvider.getRoles(); + } - when(jwt.hasClaim("realm_access")).thenReturn(false); + @Test + public void getRoles_whenRealmAccessNotPresentButResourceAccessPresent() { + Map>> resourceAccess = new HashMap<>(); + resourceAccess.put("client1", new HashMap<>(Collections.singletonMap("roles", Arrays.asList("ROLE_SUPPORT", "ROLE_USER")))); - when(jwt.hasClaim("resource_access")).thenReturn(true); - when(jwt.getClaim("resource_access")).thenReturn(resourceAccess); + when(jwt.hasClaim("realm_access")).thenReturn(false); + when(jwt.hasClaim("resource_access")).thenReturn(true); + when(jwt.getClaim("resource_access")).thenReturn(resourceAccess); - List roles = keycloakRoleProvider.getRoles(); + List roles = keycloakRoleProvider.getRoles(); - assertEquals(2, roles.size()); - assertTrue(roles.contains("ROLE_SUPPORT")); - assertTrue(roles.contains("ROLE_USER")); - } + assertEquals(2, roles.size()); + assertTrue(roles.contains("ROLE_SUPPORT")); + assertTrue(roles.contains("ROLE_USER")); + } @Test - public void getRoles_whenResourceAccessNotPresentButRealmAccessPresent() { - Map> realmAccess = new HashMap<>(); - realmAccess.put("roles", Arrays.asList("ROLE_USER", "ROLE_ADMIN")); - when(jwt.hasClaim("resource_access")).thenReturn(false); + public void getRoles_whenResourceAccessNotPresentButRealmAccessPresent() { + Map> realmAccess = new HashMap<>(); + realmAccess.put("roles", Arrays.asList("ROLE_USER", "ROLE_ADMIN")); - when(jwt.hasClaim("realm_access")).thenReturn(true); - when(jwt.getClaim("realm_access")).thenReturn(realmAccess); + when(jwt.hasClaim("resource_access")).thenReturn(false); + when(jwt.hasClaim("realm_access")).thenReturn(true); + when(jwt.getClaim("realm_access")).thenReturn(realmAccess); - List roles = keycloakRoleProvider.getRoles(); + List roles = keycloakRoleProvider.getRoles(); - assertEquals(2, roles.size()); - assertTrue(roles.contains("ROLE_USER")); - assertTrue(roles.contains("ROLE_ADMIN")); - } + assertEquals(2, roles.size()); + assertTrue(roles.contains("ROLE_USER")); + assertTrue(roles.contains("ROLE_ADMIN")); + } @Test - public void getRoles_whenClaimNotPresent() { - - when(jwt.hasClaim("realm_access")).thenReturn(false); - when(jwt.hasClaim("resource_access")).thenReturn(false); - - List roles = keycloakRoleProvider.getRoles(); - - assertTrue(roles.isEmpty()); - } + public void getRoles_whenClaimNotPresent() { + when(jwt.hasClaim("realm_access")).thenReturn(false); + when(jwt.hasClaim("resource_access")).thenReturn(false); + + List roles = keycloakRoleProvider.getRoles(); + + assertTrue(roles.isEmpty()); + } } diff --git a/ci/keycloak/realm/BaSyx-realm.json b/ci/keycloak/realm/BaSyx-realm.json index b893decf7..2b28f4c58 100644 --- a/ci/keycloak/realm/BaSyx-realm.json +++ b/ci/keycloak/realm/BaSyx-realm.json @@ -511,14 +511,14 @@ "attributes" : { } } ], "basyx-client-api" : [ { - "id" : "2dd4b9b1-748f-43f3-b62b-048c92ae79d1", + "id" : "2dd4b9b1-748f-43f3-b62b-048c92ae79d1", "name" : "basyx-creator", "description" : "", "composite" : false, "clientRole" : true, "containerId" : "3fb3e5e5-dbd8-4d51-b964-746c5b2181a4", "attributes" : { } - }, { + }, { "id" : "ba077409-1b5d-4fc8-b20e-10389507fb75", "name" : "basyx-admin", "description" : "", @@ -621,7 +621,7 @@ "clientRole" : true, "containerId" : "049e1323-6efb-4543-bc52-566cd292732a", "attributes" : { } - } ], + } ], "basyx-demo" : [ ], "workstation-1" : [ { "id" : "914a18c6-4f14-418f-99e0-bfdcf604ac01", @@ -629,7 +629,7 @@ "composite" : false, "clientRole" : true, "containerId" : "96031210-9e6c-4252-a22e-e81a47e30d65", - "attributes" : { } + "attributes" : { } } ] } }, @@ -985,9 +985,6 @@ "disableableCredentialTypes" : [ ], "requiredActions" : [ ], "realmRoles" : [ "basyx-reader", "default-roles-basyx" ], - "clientRoles" : { - "basyx-client-api" : [ "basyx-user" ] - }, "notBefore" : 0, "groups" : [ ] }, { @@ -1387,9 +1384,12 @@ "disableableCredentialTypes" : [ ], "requiredActions" : [ ], "realmRoles" : [ "visitor", "default-roles-basyx" ], + "clientRoles" : { + "basyx-client-api" : [ "basyx-user" ] + }, "notBefore" : 0, "groups" : [ ] - }, { + }, { "id" : "a19abcac-34d5-46bb-a604-b07dc234e80f", "createdTimestamp" : 1715582034760, "username" : "service-account-workstation-1", @@ -1400,7 +1400,7 @@ "credentials" : [ ], "disableableCredentialTypes" : [ ], "requiredActions" : [ ], - "realmRoles" : [ "basyx-reader", "basyx-deleter", "basyx-updater", "basyx-creator", "default-roles-basyx", "admin" ], + "realmRoles" : [ "basyx-reader", "basyx-deleter", "basyx-updater", "admin", "basyx-creator", "default-roles-basyx" ], "clientRoles" : { "workstation-1" : [ "uma_protection" ] }, @@ -1428,7 +1428,7 @@ "requiredActions" : [ ], "realmRoles" : [ "default-roles-basyx" ], "notBefore" : 0, - "groups" : [ "/BaSyxGroup" ] + "groups" : [ "/BaSyxGroup" ] } ], "scopeMappings" : [ { "clientScope" : "offline_access", @@ -1575,7 +1575,7 @@ "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] }, { - "id" : "615f29de-5f3d-4384-8b71-7351ff2c2a32", + "id" : "615f29de-5f3d-4384-8b71-7351ff2c2a32", "clientId" : "basyx-demo", "name" : "", "description" : "", @@ -1601,9 +1601,10 @@ "protocol" : "openid-connect", "attributes" : { "oidc.ciba.grant.enabled" : "false", - "oauth2.device.authorization.grant.enabled" : "false", "client.secret.creation.time" : "1716897911", "backchannel.logout.session.required" : "true", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", "backchannel.logout.revoke.offline.tokens" : "false" }, "authenticationFlowBindingOverrides" : { }, @@ -1611,7 +1612,7 @@ "nodeReRegistrationTimeout" : -1, "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { + }, { "id" : "45f21c3d-4e85-466f-984f-d7bd47392453", "clientId" : "broker", "name" : "${client_broker}", @@ -1713,7 +1714,7 @@ } ], "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { + }, { "id" : "96031210-9e6c-4252-a22e-e81a47e30d65", "clientId" : "workstation-1", "name" : "Workstation 1", @@ -1741,9 +1742,10 @@ "protocol" : "openid-connect", "attributes" : { "oidc.ciba.grant.enabled" : "false", - "oauth2.device.authorization.grant.enabled" : "false", "client.secret.creation.time" : "1715582034", "backchannel.logout.session.required" : "true", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", "backchannel.logout.revoke.offline.tokens" : "false" }, "authenticationFlowBindingOverrides" : { }, @@ -1757,6 +1759,7 @@ "consentRequired" : false, "config" : { "user.session.note" : "clientAddress", + "userinfo.token.claim" : "true", "id.token.claim" : "true", "access.token.claim" : "true", "claim.name" : "clientAddress", @@ -1770,6 +1773,7 @@ "consentRequired" : false, "config" : { "user.session.note" : "clientHost", + "userinfo.token.claim" : "true", "id.token.claim" : "true", "access.token.claim" : "true", "claim.name" : "clientHost", @@ -1783,6 +1787,7 @@ "consentRequired" : false, "config" : { "user.session.note" : "client_id", + "userinfo.token.claim" : "true", "id.token.claim" : "true", "access.token.claim" : "true", "claim.name" : "client_id", @@ -1790,7 +1795,15 @@ } } ], "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ], + "authorizationSettings" : { + "allowRemoteResourceManagement" : true, + "policyEnforcementMode" : "ENFORCING", + "resources" : [ ], + "policies" : [ ], + "scopes" : [ ], + "decisionStrategy" : "UNANIMOUS" + } } ], "clientScopes" : [ { "id" : "e0f355da-f9ff-4104-b305-043b0188747b", @@ -2288,7 +2301,7 @@ "subType" : "anonymous", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper" ] } }, { "id" : "7256d195-1e91-4f63-a9c4-6bef95243a92", @@ -2325,7 +2338,7 @@ "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "saml-user-attribute-mapper" ] + "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "oidc-address-mapper", "saml-user-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper" ] } }, { "id" : "face2c9e-4d23-44e2-9a09-74e1d8448bd3",