This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new 85b9c2e2bc [SYNCOPE-1955] Fixing filtered OIDC claim release
85b9c2e2bc is described below

commit 85b9c2e2bc286b644e51f2296326f91010cc90eb
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Wed Mar 25 12:54:13 2026 +0100

    [SYNCOPE-1955] Fixing filtered OIDC claim release
---
 .../org/apache/syncope/fit/AbstractITCase.java     |   4 +
 .../apache/syncope/fit/sra/AbstractOIDCITCase.java |  19 ++--
 .../apache/syncope/fit/sra/OAUTH2SRAITCase.java    |  10 +-
 .../org/apache/syncope/fit/sra/OIDCSRAITCase.java  | 109 +++++++++++++++++++--
 .../mapping/DefaultAttrReleaseMapper.java          |   7 +-
 .../syncope/wa/starter/config/WAContext.java       |  14 ++-
 .../oidc/WAOidcAttributeReleasePolicyFactory.java  |  89 +++++++++++++++++
 ... => WAOidcJsonWebKeystoreGeneratorService.java} |   6 +-
 .../WASurrogateAuthenticationServiceTest.java      |   3 +-
 9 files changed, 232 insertions(+), 29 deletions(-)

diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 917ae9b24c..994a5e2d3c 100644
--- a/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -41,6 +41,7 @@ import org.apache.http.message.BasicNameValuePair;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
 import org.apache.syncope.common.lib.jackson.SyncopeJsonMapper;
+import org.apache.syncope.common.rest.api.service.AttrRepoService;
 import org.apache.syncope.common.rest.api.service.ClientAppService;
 import org.apache.syncope.common.rest.api.service.ImplementationService;
 import org.apache.syncope.common.rest.api.service.OIDCC4UIProviderService;
@@ -109,6 +110,8 @@ public abstract class AbstractITCase {
 
     protected static OIDCC4UIProviderService OIDCC4UI_PROVIDER_SERVICE;
 
+    protected static AttrRepoService ATTR_REPO_SERVICE;
+
     @BeforeAll
     public static void restSetup() {
         CLIENT_FACTORY = new 
SyncopeClientFactoryBean().setAddress(CORE_ADDRESS);
@@ -124,6 +127,7 @@ public abstract class AbstractITCase {
         SRA_ROUTE_SERVICE = ADMIN_CLIENT.getService(SRARouteService.class);
         SAML2SP4UI_IDP_SERVICE = 
ADMIN_CLIENT.getService(SAML2SP4UIIdPService.class);
         OIDCC4UI_PROVIDER_SERVICE = 
ADMIN_CLIENT.getService(OIDCC4UIProviderService.class);
+        ATTR_REPO_SERVICE = ADMIN_CLIENT.getService(AttrRepoService.class);
     }
 
     @BeforeAll
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractOIDCITCase.java
 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractOIDCITCase.java
index f7282de671..a1a61a7c66 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractOIDCITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractOIDCITCase.java
@@ -67,6 +67,7 @@ import org.apache.syncope.common.lib.types.OIDCSubjectType;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
+import org.apereo.cas.support.oauth.OAuth20Constants;
 import org.jsoup.Jsoup;
 import org.junit.jupiter.api.Test;
 import tools.jackson.databind.JsonNode;
@@ -76,13 +77,19 @@ abstract class AbstractOIDCITCase extends AbstractSRAITCase 
{
 
     protected static final String GROUPS_SCOPE = "groups";
 
+    protected static final String CUSTOM_SCOPE1 = "customScope1";
+
+    protected static final String CUSTOM_CLAIM1 = "customClaim1";
+
+    protected static final String CUSTOM_CLAIM2 = "customClaim2";
+
     protected static String SRA_REGISTRATION_ID;
 
     protected static Long CLIENT_APP_ID;
 
-    protected static String CLIENT_ID;
+    protected static String SRA_CLIENT_ID;
 
-    protected static String CLIENT_SECRET;
+    protected static String SRA_CLIENT_SECRET;
 
     protected static String TOKEN_URI;
 
@@ -313,12 +320,12 @@ abstract class AbstractOIDCITCase extends 
AbstractSRAITCase {
 
         // 1. obtain id and access tokens
         Form form = new Form().
-                param("grant_type", "password").
-                param("client_id", CLIENT_ID).
-                param("client_secret", CLIENT_SECRET).
+                param(OAuth20Constants.GRANT_TYPE, 
OIDCGrantType.password.getExternalForm()).
+                param(OAuth20Constants.CLIENT_ID, SRA_CLIENT_ID).
+                param(OAuth20Constants.CLIENT_SECRET, SRA_CLIENT_SECRET).
                 param("username", "verdi").
                 param("password", "password").
-                param("scope", "openid profile email " + GROUPS_SCOPE);
+                param(OAuth20Constants.SCOPE, "openid profile email " + 
GROUPS_SCOPE);
         response = WebClient.create(TOKEN_URI).post(form);
         assertEquals(HttpStatus.SC_OK, response.getStatus());
         
assertTrue(response.getHeaderString(HttpHeaders.CONTENT_TYPE).startsWith(MediaType.APPLICATION_JSON));
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
index 1d89ac56d5..aa2689b0fe 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
@@ -53,15 +53,15 @@ class OAUTH2SRAITCase extends AbstractOIDCITCase {
         }
         SRA_REGISTRATION_ID = "OAUTH2";
         CLIENT_APP_ID = 2L;
-        CLIENT_ID = props.getProperty("sra.oauth2.client-id");
-        assertNotNull(CLIENT_ID);
-        CLIENT_SECRET = props.getProperty("sra.oauth2.client-secret");
-        assertNotNull(CLIENT_SECRET);
+        SRA_CLIENT_ID = props.getProperty("sra.oauth2.client-id");
+        assertNotNull(SRA_CLIENT_ID);
+        SRA_CLIENT_SECRET = props.getProperty("sra.oauth2.client-secret");
+        assertNotNull(SRA_CLIENT_SECRET);
         TOKEN_URI = props.getProperty("sra.oauth2.tokenUri");
         assertNotNull(TOKEN_URI);
 
         oidcClientAppSetup(
-                OAUTH2SRAITCase.class.getName(), SRA_REGISTRATION_ID, 
CLIENT_APP_ID, CLIENT_ID, CLIENT_SECRET);
+                OAUTH2SRAITCase.class.getName(), SRA_REGISTRATION_ID, 
CLIENT_APP_ID, SRA_CLIENT_ID, SRA_CLIENT_SECRET);
     }
 
     @Override
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
index 16bf410049..c1cfa5e1e5 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
@@ -18,19 +18,51 @@
  */
 package org.apache.syncope.fit.sra;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.nimbusds.jwt.SignedJWT;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.Response;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
+import java.text.ParseException;
 import java.util.Properties;
+import java.util.Set;
 import java.util.concurrent.TimeoutException;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.http.HttpStatus;
+import org.apache.syncope.common.lib.OIDCStandardScope;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.attr.StubAttrRepoConf;
+import org.apache.syncope.common.lib.policy.AttrReleasePolicyTO;
+import org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf;
+import org.apache.syncope.common.lib.to.AttrRepoTO;
+import org.apache.syncope.common.lib.to.OIDCOpEntityTO;
+import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
+import org.apache.syncope.common.lib.types.ClientAppType;
+import org.apache.syncope.common.lib.types.OIDCClientAuthenticationMethod;
+import org.apache.syncope.common.lib.types.OIDCGrantType;
+import org.apache.syncope.common.lib.types.OIDCTokenSigningAlg;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apereo.cas.support.oauth.OAuth20Constants;
 import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import tools.jackson.databind.JsonNode;
 
 class OIDCSRAITCase extends AbstractOIDCITCase {
 
+    protected static final String CLIENT_CREDENTIALS_CLIENT_ID = "Client1";
+
+    protected static final String CLIENT_CREDENTIALS_CLIENT_SECRET = "Client1";
+
     @BeforeAll
     public static void startSRA() throws IOException, InterruptedException, 
TimeoutException {
         
assumeTrue(OIDCSRAITCase.class.equals(MethodHandles.lookup().lookupClass()));
@@ -39,9 +71,50 @@ class OIDCSRAITCase extends AbstractOIDCITCase {
     }
 
     @BeforeAll
-    public static void clientAppSetup() {
+    public static void oidcTestsSetup() {
         
assumeTrue(OIDCSRAITCase.class.equals(MethodHandles.lookup().lookupClass()));
 
+        // 1. client_credentials: add custom scope
+        OIDCOpEntityTO entityTO = new OIDCOpEntityTO();
+        entityTO.getCustomScopes().put(CUSTOM_SCOPE1, Set.of(CUSTOM_CLAIM1, 
CUSTOM_CLAIM2));
+        OIDC_OP_ENTITY_SERVICE.set(entityTO);
+
+        // 2. client_credentials: define attribute repository
+        StubAttrRepoConf stubAttrRepoConf = new StubAttrRepoConf();
+        stubAttrRepoConf.getAttributes().put(CUSTOM_CLAIM1, "value1");
+        stubAttrRepoConf.getAttributes().put(CUSTOM_CLAIM2, "value2");
+        AttrRepoTO attrRepoTO = new AttrRepoTO();
+        attrRepoTO.setKey("Static");
+        attrRepoTO.setConf(stubAttrRepoConf);
+        ATTR_REPO_SERVICE.create(attrRepoTO);
+
+        // 3. client_credentials: add attribute release policy
+        DefaultAttrReleasePolicyConf conf = new DefaultAttrReleasePolicyConf();
+        conf.getReleaseAttrs().put(CUSTOM_CLAIM1, CUSTOM_CLAIM1);
+        conf.getPrincipalAttrRepoConf().getAttrRepos().add("Static");
+        AttrReleasePolicyTO policy = new AttrReleasePolicyTO();
+        policy.setName("Filtered");
+        policy.setConf(conf);
+        Response response = POLICY_SERVICE.create(PolicyType.ATTR_RELEASE, 
policy);
+        String policyKey = response.getHeaderString(RESTHeaders.RESOURCE_KEY);
+
+        // 4. client_credentials: add client application
+        OIDCRPClientAppTO clientCredentialsApp = new OIDCRPClientAppTO();
+        clientCredentialsApp.setRealm(SyncopeConstants.ROOT_REALM);
+        clientCredentialsApp.setClientAppId(999L);
+        clientCredentialsApp.setName("Client1");
+        clientCredentialsApp.setClientId(CLIENT_CREDENTIALS_CLIENT_ID);
+        clientCredentialsApp.setClientSecret(CLIENT_CREDENTIALS_CLIENT_SECRET);
+        clientCredentialsApp.setAttrReleasePolicy(policyKey);
+        clientCredentialsApp.getRedirectUris().add("https://www.apache.org";);
+        clientCredentialsApp.setJwtAccessToken(true);
+        clientCredentialsApp.setIdTokenSigningAlg(OIDCTokenSigningAlg.RS256);
+        clientCredentialsApp.getScopes().add(OIDCStandardScope.openid.name());
+        clientCredentialsApp.getScopes().add(CUSTOM_SCOPE1);
+        
clientCredentialsApp.setTokenEndpointAuthenticationMethod(OIDCClientAuthenticationMethod.client_secret_post);
+        CLIENT_APP_SERVICE.create(ClientAppType.OIDCRP, clientCredentialsApp);
+
+        // 5. prepare for SRA test cases
         Properties props = new Properties();
         try (InputStream propStream = 
OIDCSRAITCase.class.getResourceAsStream("/sra-oidc.properties")) {
             props.load(propStream);
@@ -50,18 +123,42 @@ class OIDCSRAITCase extends AbstractOIDCITCase {
         }
         SRA_REGISTRATION_ID = "OIDC";
         CLIENT_APP_ID = 1L;
-        CLIENT_ID = props.getProperty("sra.oidc.client-id");
-        assertNotNull(CLIENT_ID);
-        CLIENT_SECRET = props.getProperty("sra.oidc.client-secret");
-        assertNotNull(CLIENT_SECRET);
+        SRA_CLIENT_ID = props.getProperty("sra.oidc.client-id");
+        assertNotNull(SRA_CLIENT_ID);
+        SRA_CLIENT_SECRET = props.getProperty("sra.oidc.client-secret");
+        assertNotNull(SRA_CLIENT_SECRET);
         TOKEN_URI = WA_ADDRESS + "/oidc/accessToken";
 
         oidcClientAppSetup(
-                OIDCSRAITCase.class.getName(), SRA_REGISTRATION_ID, 
CLIENT_APP_ID, CLIENT_ID, CLIENT_SECRET);
+                OIDCSRAITCase.class.getName(), SRA_REGISTRATION_ID, 
CLIENT_APP_ID, SRA_CLIENT_ID, SRA_CLIENT_SECRET);
     }
 
     @Override
     protected boolean checkIdToken() {
         return true;
     }
+
+    @Test
+    public void clientCredentials() throws JsonProcessingException, 
ParseException {
+        WebClient webclient = WebClient.create(WA_ADDRESS + 
"/oidc/oidcAccessToken");
+        Form form = new Form().
+                param(OAuth20Constants.GRANT_TYPE, 
OIDCGrantType.client_credentials.getExternalForm()).
+                param(OAuth20Constants.CLIENT_ID, 
CLIENT_CREDENTIALS_CLIENT_ID).
+                param(OAuth20Constants.CLIENT_SECRET, 
CLIENT_CREDENTIALS_CLIENT_SECRET).
+                param(OAuth20Constants.SCOPE, "openid customScope1");
+        Response response = webclient.form(form);
+        assertEquals(HttpStatus.SC_OK, response.getStatus());
+
+        JsonNode json = MAPPER.readTree(response.readEntity(String.class));
+
+        assertTrue(json.has("access_token"));
+        SignedJWT accessToken = 
SignedJWT.parse(json.get("access_token").asString());
+        assertNotNull(accessToken.getJWTClaimsSet().getClaim(CUSTOM_CLAIM1));
+        assertNull(accessToken.getJWTClaimsSet().getClaim(CUSTOM_CLAIM2));
+
+        assertTrue(json.has("id_token"));
+        SignedJWT idToken = SignedJWT.parse(json.get("id_token").asString());
+        assertNotNull(idToken.getJWTClaimsSet().getClaim(CUSTOM_CLAIM1));
+        assertNull(idToken.getJWTClaimsSet().getClaim(CUSTOM_CLAIM2));
+    }
 }
diff --git 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/DefaultAttrReleaseMapper.java
 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/DefaultAttrReleaseMapper.java
index 6ead2e27b5..f7fc7325b6 100644
--- 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/DefaultAttrReleaseMapper.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/DefaultAttrReleaseMapper.java
@@ -40,7 +40,6 @@ import 
org.apereo.cas.oidc.claims.BaseOidcScopeAttributeReleasePolicy;
 import org.apereo.cas.oidc.claims.OidcAddressScopeAttributeReleasePolicy;
 import org.apereo.cas.oidc.claims.OidcCustomScopeAttributeReleasePolicy;
 import org.apereo.cas.oidc.claims.OidcEmailScopeAttributeReleasePolicy;
-import org.apereo.cas.oidc.claims.OidcOpenIdScopeAttributeReleasePolicy;
 import org.apereo.cas.oidc.claims.OidcPhoneScopeAttributeReleasePolicy;
 import org.apereo.cas.oidc.claims.OidcProfileScopeAttributeReleasePolicy;
 import org.apereo.cas.services.AbstractRegisteredServiceAttributeReleasePolicy;
@@ -220,9 +219,6 @@ public class DefaultAttrReleaseMapper implements 
AttrReleaseMapper {
 
         Map<String, BaseOidcScopeAttributeReleasePolicy> policies = new 
HashMap<>();
 
-        if (clientApp.getScopes().contains(OIDCStandardScope.openid.name())) {
-            policies.put(OIDCStandardScope.openid.name(), new 
OidcOpenIdScopeAttributeReleasePolicy());
-        }
         conf.getReleaseAttrs().forEach((internal, external) -> {
             if 
(OidcProfileScopeAttributeReleasePolicy.ALLOWED_CLAIMS.contains(external.toString()))
 {
                 buildForOIDCStandardScope(
@@ -258,7 +254,8 @@ public class DefaultAttrReleaseMapper implements 
AttrReleaseMapper {
                         external.toString());
             } else {
                 oidcOpEntity.getCustomScopes().entrySet().stream().
-                        filter(entry -> 
entry.getValue().contains(external.toString())).
+                        filter(entry -> 
clientApp.getScopes().contains(entry.getKey())
+                        && entry.getValue().contains(external.toString())).
                         map(Map.Entry::getKey).findFirst().ifPresentOrElse(
                         scope -> buildForOIDCustomScope(
                                 clientApp, policies, scope, internal, 
external.toString()),
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java
index c18fdb5553..75ccbec7ed 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java
@@ -61,7 +61,8 @@ import 
org.apache.syncope.wa.starter.mapping.SAML2SPClientAppTOMapper;
 import org.apache.syncope.wa.starter.mapping.TicketExpirationMapper;
 import org.apache.syncope.wa.starter.mapping.TimeBasedAccessMapper;
 import 
org.apache.syncope.wa.starter.mfa.WAMultifactorAuthenticationTrustStorage;
-import org.apache.syncope.wa.starter.oidc.WAOIDCJWKSGeneratorService;
+import org.apache.syncope.wa.starter.oidc.WAOidcAttributeReleasePolicyFactory;
+import 
org.apache.syncope.wa.starter.oidc.WAOidcJsonWebKeystoreGeneratorService;
 import org.apache.syncope.wa.starter.pac4j.saml.WASAML2ClientCustomizer;
 import 
org.apache.syncope.wa.starter.saml.idp.metadata.WASamlIdPMetadataCacheRefresher;
 import 
org.apache.syncope.wa.starter.saml.idp.metadata.WASamlIdPMetadataGenerator;
@@ -80,6 +81,7 @@ import 
org.apereo.cas.configuration.model.support.pm.PasswordManagementPropertie
 import org.apereo.cas.gauth.CasGoogleAuthenticator;
 import 
org.apereo.cas.gauth.credential.LdapGoogleAuthenticatorTokenCredentialRepository;
 import org.apereo.cas.oidc.jwks.generator.OidcJsonWebKeystoreGeneratorService;
+import org.apereo.cas.oidc.scopes.OidcAttributeReleasePolicyFactory;
 import 
org.apereo.cas.otp.repository.credentials.OneTimeTokenCredentialRepository;
 import org.apereo.cas.pm.LdapPasswordManagementService;
 import org.apereo.cas.pm.PasswordHistoryService;
@@ -525,7 +527,7 @@ public class WAContext {
             final WARestClient waRestClient,
             final ApplicationContext applicationContext) {
 
-        return new WAOIDCJWKSGeneratorService(
+        return new WAOidcJsonWebKeystoreGeneratorService(
                 waRestClient,
                 
casProperties.getAuthn().getOidc().getJwks().getCore().getJwksKeyId(),
                 
casProperties.getAuthn().getOidc().getJwks().getCore().getJwksType(),
@@ -533,6 +535,14 @@ public class WAContext {
                 applicationContext);
     }
 
+    @Bean
+    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
+    public OidcAttributeReleasePolicyFactory oidcAttributeReleasePolicyFactory(
+            final CasConfigurationProperties casProperties) {
+
+        return new WAOidcAttributeReleasePolicyFactory(casProperties);
+    }
+
     @Bean
     public WebAuthnCredentialRepository webAuthnCredentialRepository(
             final CasConfigurationProperties casProperties,
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/WAOidcAttributeReleasePolicyFactory.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/WAOidcAttributeReleasePolicyFactory.java
new file mode 100644
index 0000000000..b9bc7a7f10
--- /dev/null
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/WAOidcAttributeReleasePolicyFactory.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.wa.starter.oidc;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apereo.cas.configuration.CasConfigurationProperties;
+import org.apereo.cas.oidc.claims.BaseOidcScopeAttributeReleasePolicy;
+import org.apereo.cas.oidc.claims.OidcCustomScopeAttributeReleasePolicy;
+import org.apereo.cas.oidc.claims.OidcRegisteredServiceAttributeReleasePolicy;
+import org.apereo.cas.oidc.claims.OidcScopeFreeAttributeReleasePolicy;
+import org.apereo.cas.oidc.scopes.DefaultOidcAttributeReleasePolicyFactory;
+import org.apereo.cas.services.ChainingAttributeReleasePolicy;
+import org.apereo.cas.services.OidcRegisteredService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WAOidcAttributeReleasePolicyFactory extends 
DefaultOidcAttributeReleasePolicyFactory {
+
+    protected static final Logger LOG = 
LoggerFactory.getLogger(WAOidcAttributeReleasePolicyFactory.class);
+
+    public WAOidcAttributeReleasePolicyFactory(final 
CasConfigurationProperties casProperties) {
+        super(casProperties);
+    }
+
+    @Override
+    public Map<String, BaseOidcScopeAttributeReleasePolicy> resolvePolicies(
+            final OidcRegisteredService registeredService) {
+
+        Map<String, BaseOidcScopeAttributeReleasePolicy> policies = new 
HashMap<>(attributeReleasePoliciesByScope);
+
+        Collection<OidcCustomScopeAttributeReleasePolicy> userScopes = 
getUserDefinedScopes();
+        LOG.debug("Configuring attributes release policies for user-defined 
scopes [{}]", userScopes);
+        userScopes.forEach(us -> policies.put(us.getScopeName(), us));
+
+        LOG.debug("Configuring attributes release policies for user-defined 
scopes specified for service [{}]",
+                registeredService.getName());
+
+        List<OidcRegisteredServiceAttributeReleasePolicy> listOfOidcPolicies = 
new ArrayList<>();
+        switch (registeredService.getAttributeReleasePolicy()) {
+            case ChainingAttributeReleasePolicy chain ->
+                listOfOidcPolicies.addAll(chain.getPolicies().stream().
+                        
filter(OidcRegisteredServiceAttributeReleasePolicy.class::isInstance).
+                        
map(OidcRegisteredServiceAttributeReleasePolicy.class::cast).
+                        toList());
+
+            case OidcRegisteredServiceAttributeReleasePolicy policy ->
+                listOfOidcPolicies.add(policy);
+
+            case null -> {
+            }
+
+            default -> {
+            }
+        }
+
+        listOfOidcPolicies.stream().
+                
filter(OidcCustomScopeAttributeReleasePolicy.class::isInstance).
+                map(OidcCustomScopeAttributeReleasePolicy.class::cast).
+                forEach(policy -> policies.put(policy.getScopeName(), policy));
+        listOfOidcPolicies.stream().
+                filter(OidcScopeFreeAttributeReleasePolicy.class::isInstance).
+                map(OidcScopeFreeAttributeReleasePolicy.class::cast).
+                forEach(policy -> policies.put(UUID.randomUUID().toString(), 
policy));
+
+        LOG.debug("Final set of scopes mapped to attribute release policies 
are [{}]", policies.keySet());
+        return policies;
+    }
+}
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/WAOIDCJWKSGeneratorService.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/WAOidcJsonWebKeystoreGeneratorService.java
similarity index 95%
rename from 
wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/WAOIDCJWKSGeneratorService.java
rename to 
wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/WAOidcJsonWebKeystoreGeneratorService.java
index 2c7985e4b4..877d54b2d2 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/WAOIDCJWKSGeneratorService.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/WAOidcJsonWebKeystoreGeneratorService.java
@@ -38,9 +38,9 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.core.io.ByteArrayResource;
 import org.springframework.core.io.Resource;
 
-public class WAOIDCJWKSGeneratorService implements 
OidcJsonWebKeystoreGeneratorService {
+public class WAOidcJsonWebKeystoreGeneratorService implements 
OidcJsonWebKeystoreGeneratorService {
 
-    protected static final Logger LOG = 
LoggerFactory.getLogger(WAOIDCJWKSGeneratorService.class);
+    protected static final Logger LOG = 
LoggerFactory.getLogger(WAOidcJsonWebKeystoreGeneratorService.class);
 
     protected final WARestClient waRestClient;
 
@@ -52,7 +52,7 @@ public class WAOIDCJWKSGeneratorService implements 
OidcJsonWebKeystoreGeneratorS
 
     protected final ApplicationContext applicationContext;
 
-    public WAOIDCJWKSGeneratorService(
+    public WAOidcJsonWebKeystoreGeneratorService(
             final WARestClient waRestClient,
             final String jwksKeyId,
             final String jwksType,
diff --git 
a/wa/starter/src/test/java/org/apache/syncope/wa/starter/surrogate/WASurrogateAuthenticationServiceTest.java
 
b/wa/starter/src/test/java/org/apache/syncope/wa/starter/surrogate/WASurrogateAuthenticationServiceTest.java
index 4fae8f43cd..9868e5d321 100644
--- 
a/wa/starter/src/test/java/org/apache/syncope/wa/starter/surrogate/WASurrogateAuthenticationServiceTest.java
+++ 
b/wa/starter/src/test/java/org/apache/syncope/wa/starter/surrogate/WASurrogateAuthenticationServiceTest.java
@@ -43,8 +43,7 @@ public class WASurrogateAuthenticationServiceTest extends 
AbstractTest {
     @Test
     public void verifyImpersonation() throws Throwable {
         String owner = "syncope-principal";
-        ImpersonationAccount account = new ImpersonationAccount.Builder().
-                impersonated("impersonatee").build();
+        ImpersonationAccount account = new 
ImpersonationAccount.Builder().impersonated("impersonatee").build();
 
         ImpersonationService impersonationService = 
waRestClient.getService(ImpersonationService.class);
 

Reply via email to