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);