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

commit 51cf43262f79775228a439ae336c04598269af04
Author: Francesco Chicchiriccò <ilgro...@apache.org>
AuthorDate: Fri Jan 27 11:09:44 2023 +0100

    Upgrading pac4j
---
 .../console/src/main/resources/console.properties  |   1 +
 .../src/test/resources/console-debug.properties    |   4 +-
 .../enduser/src/main/resources/enduser.properties  |   1 +
 core/starter/src/main/resources/core.properties    |   1 +
 .../apache/syncope/core/logic/OIDCC4UILogic.java   |   5 +-
 .../syncope/core/logic/oidc/OIDCClientCache.java   |  31 +++---
 .../apache/syncope/core/logic/SAML2SP4UILogic.java | 104 +++++++++++----------
 .../syncope/core/logic/saml2/SAML2ClientCache.java |  15 ++-
 .../core/logic/saml2/SAML2SP4UIContext.java        |  18 ++--
 fit/wa-reference/src/main/resources/log4j2.xml     |   3 +
 .../org/apache/syncope/fit/sra/SAML2SRAITCase.java |   3 +-
 .../apache/syncope/fit/ui/SAML2SP4UIITCase.java    |   3 +-
 pom.xml                                            |   6 +-
 .../org/apache/syncope/sra/SecurityConfig.java     |  15 ++-
 .../sra/security/pac4j/RedirectionActionUtils.java |  18 ++--
 .../security/saml2/SAML2AuthenticationToken.java   |  15 +--
 .../saml2/SAML2LogoutResponseWebFilter.java        |  79 +++-------------
 .../saml2/SAML2RequestServerLogoutHandler.java     |  10 +-
 .../security/saml2/SAML2SecurityConfigUtils.java   |   2 +-
 .../SAML2WebSsoAuthenticationRequestWebFilter.java |  17 +++-
 .../saml2/SAML2WebSsoAuthenticationWebFilter.java  |  30 +++---
 sra/src/main/resources/sra.properties              |   1 +
 .../syncope/wa/starter/config/WAContext.java       |  80 ++++++++++------
 .../saml/idp/WASamlIdPCasEventListener.java        |  26 ++----
 ...erator.java => WASamlIdPMetadataGenerator.java} |  42 ++++++---
 ...aLocator.java => WASamlIdPMetadataLocator.java} |  25 +++--
 .../wa/starter/services/WAServiceRegistry.java     |  20 ++--
 wa/starter/src/main/resources/wa.properties        |   1 +
 28 files changed, 295 insertions(+), 281 deletions(-)

diff --git a/client/idrepo/console/src/main/resources/console.properties 
b/client/idrepo/console/src/main/resources/console.properties
index 44dbf8186d..173d5e5aa4 100644
--- a/client/idrepo/console/src/main/resources/console.properties
+++ b/client/idrepo/console/src/main/resources/console.properties
@@ -27,6 +27,7 @@ server.servlet.contextPath=/syncope-console
 
 management.endpoints.web.exposure.include=info,health,loggers
 management.endpoint.health.show-details=ALWAYS
+management.endpoint.env.show-values=WHEN_AUTHORIZED
 
 service.discovery.address=http://localhost:8080/syncope-console/
 
diff --git a/client/idrepo/console/src/test/resources/console-debug.properties 
b/client/idrepo/console/src/test/resources/console-debug.properties
index 8472125348..d41b7337e0 100644
--- a/client/idrepo/console/src/test/resources/console-debug.properties
+++ b/client/idrepo/console/src/test/resources/console-debug.properties
@@ -14,8 +14,8 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-keymaster.address=http://localhost:9080/syncope/rest/keymaster
-#keymaster.address=https://localhost:9443/syncope/rest/keymaster
+#keymaster.address=http://localhost:9080/syncope/rest/keymaster
+keymaster.address=https://localhost:9443/syncope/rest/keymaster
 keymaster.username=${anonymousUser}
 keymaster.password=${anonymousKey}
 
diff --git a/client/idrepo/enduser/src/main/resources/enduser.properties 
b/client/idrepo/enduser/src/main/resources/enduser.properties
index cf0af9ccc8..c7296757c3 100644
--- a/client/idrepo/enduser/src/main/resources/enduser.properties
+++ b/client/idrepo/enduser/src/main/resources/enduser.properties
@@ -27,6 +27,7 @@ server.servlet.contextPath=/syncope-enduser
 
 management.endpoints.web.exposure.include=info,health,loggers
 management.endpoint.health.show-details=ALWAYS
+management.endpoint.env.show-values=WHEN_AUTHORIZED
 
 service.discovery.address=http://localhost:8080/syncope-enduser/
 
diff --git a/core/starter/src/main/resources/core.properties 
b/core/starter/src/main/resources/core.properties
index 933aed4181..f75601eef6 100644
--- a/core/starter/src/main/resources/core.properties
+++ b/core/starter/src/main/resources/core.properties
@@ -29,6 +29,7 @@ cxf.path=/rest
 
 management.endpoints.web.exposure.include=health,info,loggers,entityCache
 management.endpoint.health.show-details=ALWAYS
+management.endpoint.env.show-values=WHEN_AUTHORIZED
 
 service.discovery.address=http://localhost:8080/syncope/rest/
 
diff --git 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
index 24fe4b0ee7..d3b5fb72bc 100644
--- 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
+++ 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
@@ -54,7 +54,6 @@ import 
org.apache.syncope.core.spring.security.AuthDataAccessor;
 import org.apache.syncope.core.spring.security.Encryptor;
 import org.pac4j.core.context.CallContext;
 import org.pac4j.core.exception.http.WithLocationAction;
-import org.pac4j.core.profile.factory.ProfileManagerFactory;
 import org.pac4j.oidc.client.OidcClient;
 import org.pac4j.oidc.credentials.OidcCredentials;
 import org.pac4j.oidc.profile.OidcProfile;
@@ -113,7 +112,7 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
 
         // 2. create OIDCRequest
         WithLocationAction action = oidcClient.getRedirectionAction(
-                new CallContext(new OIDC4UIContext(), 
NoOpSessionStore.INSTANCE, ProfileManagerFactory.DEFAULT)).
+                new CallContext(new OIDC4UIContext(), 
NoOpSessionStore.INSTANCE)).
                 map(WithLocationAction.class::cast).
                 orElseThrow(() -> {
                     SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Unknown);
@@ -275,7 +274,7 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         profile.setIdTokenString((String) 
claimsSet.getClaim(JWT_CLAIM_ID_TOKEN));
 
         WithLocationAction action = oidcClient.getLogoutAction(
-                new CallContext(new OIDC4UIContext(), 
NoOpSessionStore.INSTANCE, ProfileManagerFactory.DEFAULT),
+                new CallContext(new OIDC4UIContext(), 
NoOpSessionStore.INSTANCE),
                 profile,
                 redirectURI).
                 map(WithLocationAction.class::cast).
diff --git 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCClientCache.java
 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCClientCache.java
index 4304e677dd..19ea7c3ab6 100644
--- 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCClientCache.java
+++ 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCClientCache.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.logic.oidc;
 
+import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.oauth2.sdk.ParseException;
 import com.nimbusds.oauth2.sdk.id.Issuer;
 import com.nimbusds.openid.connect.sdk.SubjectType;
@@ -31,6 +32,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
+import java.util.function.Function;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.OIDCC4UIProviderTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
@@ -38,6 +40,7 @@ import 
org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider;
 import org.pac4j.core.http.callback.NoParameterCallbackUrlResolver;
 import org.pac4j.oidc.client.OidcClient;
 import org.pac4j.oidc.config.OidcConfiguration;
+import org.pac4j.oidc.metadata.StaticOidcOpMetadataResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,18 +51,21 @@ public class OIDCClientCache {
 
     protected static final Logger LOG = 
LoggerFactory.getLogger(OIDCClientCache.class);
 
+    protected static final Function<String, String> DISCOVERY_URI =
+            issuer -> issuer + "/.well-known/openid-configuration";
+
     protected final List<OidcClient> cache = Collections.synchronizedList(new 
ArrayList<>());
 
     protected static OIDCProviderMetadata getDiscoveryDocument(final String 
issuer) {
-        String discoveryDocumentURL = issuer + 
"/.well-known/openid-configuration";
+        String discoveryDocumentURI = DISCOVERY_URI.apply(issuer);
         try {
             HttpResponse<String> response = 
HttpClient.newBuilder().build().send(
-                    
HttpRequest.newBuilder(URI.create(discoveryDocumentURL)).GET().build(),
+                    
HttpRequest.newBuilder(URI.create(discoveryDocumentURI)).GET().build(),
                     HttpResponse.BodyHandlers.ofString());
 
             return OIDCProviderMetadata.parse(response.body());
         } catch (IOException | InterruptedException | ParseException e) {
-            LOG.error("While getting the Discovery Document at {}", 
discoveryDocumentURL, e);
+            LOG.error("While getting the Discovery Document at {}", 
discoveryDocumentURI, e);
 
             SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Unknown);
             sce.getElements().add(e.getMessage());
@@ -93,6 +99,7 @@ public class OIDCClientCache {
                 new Issuer(op.getIssuer()),
                 List.of(SubjectType.PUBLIC),
                 
Optional.ofNullable(op.getJwksUri()).map(URI::create).orElse(null));
+        metadata.setIDTokenJWSAlgs(List.of(JWSAlgorithm.HS256));
         metadata.setAuthorizationEndpointURI(
                 
Optional.ofNullable(op.getAuthorizationEndpoint()).map(URI::create).orElse(null));
         metadata.setTokenEndpointURI(
@@ -102,15 +109,17 @@ public class OIDCClientCache {
         metadata.setEndSessionEndpointURI(
                 
Optional.ofNullable(op.getEndSessionEndpoint()).map(URI::create).orElse(null));
 
-        OidcConfiguration config = new OidcConfiguration();
-        config.setClientId(op.getClientID());
-        config.setSecret(op.getClientSecret());
-        config.setProviderMetadata(metadata);
-        config.setScope("openid profile email address phone offline_access");
-        config.setUseNonce(false);
-        config.setSessionLogoutHandler(new NoOpSessionLogoutHandler());
+        OidcConfiguration cfg = new OidcConfiguration();
+        cfg.setClientId(op.getClientID());
+        cfg.setSecret(op.getClientSecret());
+        cfg.setDiscoveryURI(DISCOVERY_URI.apply(op.getIssuer()));
+        cfg.setPreferredJwsAlgorithm(JWSAlgorithm.HS256);
+        cfg.setOpMetadataResolver(new StaticOidcOpMetadataResolver(cfg, 
metadata));
+        cfg.setScope("openid profile email address phone offline_access");
+        cfg.setUseNonce(false);
+        cfg.setSessionLogoutHandler(new NoOpSessionLogoutHandler());
 
-        OidcClient client = new OidcClient(config);
+        OidcClient client = new OidcClient(cfg);
         client.setName(op.getName());
         client.setCallbackUrlResolver(new NoParameterCallbackUrlResolver());
         client.setCallbackUrl(callbackUrl);
diff --git 
a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
 
b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
index 264574b521..55d1d9598a 100644
--- 
a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
+++ 
b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
@@ -72,14 +72,15 @@ import 
org.opensaml.saml.saml2.metadata.AssertionConsumerService;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml.saml2.metadata.impl.AssertionConsumerServiceBuilder;
 import org.pac4j.core.context.CallContext;
+import org.pac4j.core.credentials.Credentials;
 import org.pac4j.core.exception.http.RedirectionAction;
 import org.pac4j.core.exception.http.WithContentAction;
 import org.pac4j.core.exception.http.WithLocationAction;
 import org.pac4j.core.logout.NoLogoutActionBuilder;
-import org.pac4j.core.profile.factory.ProfileManagerFactory;
 import org.pac4j.saml.client.SAML2Client;
 import org.pac4j.saml.config.SAML2Configuration;
 import org.pac4j.saml.context.SAML2MessageContext;
+import org.pac4j.saml.credentials.SAML2AuthenticationCredentials;
 import org.pac4j.saml.credentials.SAML2Credentials;
 import org.pac4j.saml.credentials.authenticator.SAML2Authenticator;
 import org.pac4j.saml.metadata.SAML2ServiceProviderMetadataResolver;
@@ -102,6 +103,28 @@ public class SAML2SP4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
 
     protected static final Encryptor ENCRYPTOR = Encryptor.getInstance();
 
+    protected static String validateUrl(final String url) {
+        boolean isValid = true;
+        if (url.contains("..")) {
+            isValid = false;
+        }
+        if (isValid) {
+            isValid = ResourceUtils.isUrl(url);
+        }
+
+        if (!isValid) {
+            SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Unknown);
+            sce.getElements().add("Invalid URL: " + url);
+            throw sce;
+        }
+
+        return url;
+    }
+
+    protected static String getCallbackUrl(final String spEntityID, final 
String urlContext) {
+        return validateUrl(spEntityID + urlContext + "/assertion-consumer");
+    }
+
     protected final SAML2SP4UILoader loader;
 
     protected final AccessTokenDataBinder accessTokenDataBinder;
@@ -134,28 +157,6 @@ public class SAML2SP4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         this.authDataAccessor = authDataAccessor;
     }
 
-    protected static String validateUrl(final String url) {
-        boolean isValid = true;
-        if (url.contains("..")) {
-            isValid = false;
-        }
-        if (isValid) {
-            isValid = ResourceUtils.isUrl(url);
-        }
-
-        if (!isValid) {
-            SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Unknown);
-            sce.getElements().add("Invalid URL: " + url);
-            throw sce;
-        }
-
-        return url;
-    }
-
-    protected static String getCallbackUrl(final String spEntityID, final 
String urlContext) {
-        return validateUrl(spEntityID + urlContext + "/assertion-consumer");
-    }
-
     @PreAuthorize("isAuthenticated()")
     public void getMetadata(final String spEntityID, final String urlContext, 
final OutputStream os) {
         String metadata = metadataCache.get(spEntityID + urlContext);
@@ -221,17 +222,13 @@ public class SAML2SP4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         return getSAML2Client(idp, spEntityID, urlContext);
     }
 
-    protected static SAML2Request buildRequest(final String idpEntityID, final 
RedirectionAction action) {
+    protected SAML2Request buildRequest(final String idpEntityID, final 
RedirectionAction action) {
         SAML2Request requestTO = new SAML2Request();
         requestTO.setIdpEntityID(idpEntityID);
-        if (action instanceof WithLocationAction) {
-            WithLocationAction withLocationAction = (WithLocationAction) 
action;
-
+        if (action instanceof WithLocationAction withLocationAction) {
             requestTO.setBindingType(SAML2BindingType.REDIRECT);
             requestTO.setContent(withLocationAction.getLocation());
-        } else if (action instanceof WithContentAction) {
-            WithContentAction withContentAction = (WithContentAction) action;
-
+        } else if (action instanceof WithContentAction withContentAction) {
             requestTO.setBindingType(SAML2BindingType.POST);
             
requestTO.setContent(Base64.getMimeEncoder().encodeToString(withContentAction.getContent().getBytes()));
         }
@@ -294,7 +291,7 @@ public class SAML2SP4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
                 saml2Client.getConfiguration().getAuthnRequestBindingType(),
                 null);
         RedirectionAction action = saml2Client.getRedirectionAction(
-                new CallContext(ctx, NoOpSessionStore.INSTANCE, 
ProfileManagerFactory.DEFAULT)).
+                new CallContext(ctx, NoOpSessionStore.INSTANCE)).
                 orElseThrow(() -> {
                     SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Unknown);
                     sce.getElements().add("No RedirectionAction generated for 
AuthnRequest");
@@ -315,17 +312,20 @@ public class SAML2SP4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         SAML2Client saml2Client = getSAML2Client(idp, 
saml2Response.getSpEntityID(), saml2Response.getUrlContext());
 
         // 2. validate the provided SAML response
-        SAML2Credentials credentials;
-        try {
-            SAML2SP4UIContext ctx = new SAML2SP4UIContext(
-                    
saml2Client.getConfiguration().getAuthnRequestBindingType(),
-                    saml2Response);
+        SAML2SP4UIContext webCtx = new SAML2SP4UIContext(
+                saml2Client.getConfiguration().getAuthnRequestBindingType(),
+                saml2Response);
+        CallContext ctx = new CallContext(webCtx, NoOpSessionStore.INSTANCE);
 
-            credentials = (SAML2Credentials) 
saml2Client.getCredentialsExtractor().
-                    extract(new CallContext(ctx, NoOpSessionStore.INSTANCE, 
ProfileManagerFactory.DEFAULT)).
-                    orElseThrow(() -> new IllegalStateException("No 
AuthnResponse found"));
+        SAML2AuthenticationCredentials authCreds;
+        try {
+            Credentials creds = saml2Client.getCredentialsExtractor().
+                    extract(ctx).
+                    orElseThrow(() -> new IllegalStateException("Could not 
extract credentials"));
 
-            saml2Client.getAuthenticator().validate(new CallContext(ctx, 
NoOpSessionStore.INSTANCE), credentials);
+            authCreds = saml2Client.validateCredentials(ctx, creds).
+                    map(SAML2AuthenticationCredentials.class::cast).
+                    orElseThrow(() -> new IllegalArgumentException("Invalid 
SAML credentials provided"));
         } catch (Exception e) {
             LOG.error("While validating AuthnResponse", e);
             SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Unknown);
@@ -338,7 +338,7 @@ public class SAML2SP4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         loginResp.setIdp(saml2Client.getIdentityProviderResolvedEntityId());
         loginResp.setSloSupported(!(saml2Client.getLogoutActionBuilder() 
instanceof NoLogoutActionBuilder));
 
-        SAML2Credentials.SAMLNameID nameID = credentials.getNameId();
+        SAML2AuthenticationCredentials.SAMLNameID nameID = 
authCreds.getNameId();
 
         Item connObjectKeyItem = idp.getConnObjectKeyItem().orElse(null);
 
@@ -350,11 +350,11 @@ public class SAML2SP4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
             keyValue = nameID.getValue();
         }
 
-        loginResp.setNotOnOrAfter(new 
Date(credentials.getConditions().getNotOnOrAfter().toInstant().toEpochMilli()));
+        loginResp.setNotOnOrAfter(new 
Date(authCreds.getConditions().getNotOnOrAfter().toInstant().toEpochMilli()));
 
-        loginResp.setSessionIndex(credentials.getSessionIndex());
+        loginResp.setSessionIndex(authCreds.getSessionIndex());
 
-        for (SAML2Credentials.SAMLAttribute attr : 
credentials.getAttributes()) {
+        for (SAML2AuthenticationCredentials.SAMLAttribute attr : 
authCreds.getAttributes()) {
             if (!attr.getAttributeValues().isEmpty()) {
                 String attrName = attr.getFriendlyName() == null ? 
attr.getName() : attr.getFriendlyName();
                 if (connObjectKeyItem != null && 
attrName.equals(connObjectKeyItem.getExtAttrName())) {
@@ -477,7 +477,7 @@ public class SAML2SP4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         SAML2SP4UIContext ctx = new SAML2SP4UIContext(
                 
saml2Client.getConfiguration().getSpLogoutRequestBindingType(), null);
         RedirectionAction action = saml2Client.getLogoutAction(
-                new CallContext(ctx, NoOpSessionStore.INSTANCE, 
ProfileManagerFactory.DEFAULT),
+                new CallContext(ctx, NoOpSessionStore.INSTANCE),
                 saml2Profile,
                 null).
                 orElseThrow(() -> {
@@ -504,17 +504,19 @@ public class SAML2SP4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         }
 
         // 2. validate the provided SAML response
-        SAML2SP4UIContext ctx = new SAML2SP4UIContext(
-                saml2Client.getConfiguration().getSpLogoutRequestBindingType(),
+        SAML2SP4UIContext webCtx = new SAML2SP4UIContext(
+                saml2Client.getConfiguration().getAuthnRequestBindingType(),
                 saml2Response);
+        CallContext ctx = new CallContext(webCtx, NoOpSessionStore.INSTANCE);
 
         LogoutResponse logoutResponse;
         try {
-            SAML2MessageContext saml2Ctx = 
saml2Client.getContextProvider().buildContext(
-                    new CallContext(ctx, NoOpSessionStore.INSTANCE, 
ProfileManagerFactory.DEFAULT), saml2Client);
-            saml2Client.getLogoutProfileHandler().receive(saml2Ctx);
+            Credentials creds = saml2Client.getCredentialsExtractor().
+                    extract(ctx).
+                    orElseThrow(() -> new IllegalStateException("Could not 
extract credentials"));
 
-            logoutResponse = (LogoutResponse) 
saml2Ctx.getMessageContext().getMessage();
+            saml2Client.getLogoutProcessor().processLogout(ctx, creds);
+            logoutResponse = (LogoutResponse) ((SAML2Credentials) 
creds).getContext().getMessageContext().getMessage();
         } catch (Exception e) {
             LOG.error("Could not validate LogoutResponse", e);
             return;
diff --git 
a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2ClientCache.java
 
b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2ClientCache.java
index 945d2587f6..15577bcc34 100644
--- 
a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2ClientCache.java
+++ 
b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2ClientCache.java
@@ -27,6 +27,7 @@ import java.util.Base64;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.syncope.common.lib.to.Item;
@@ -125,7 +126,19 @@ public class SAML2ClientCache {
     public SAML2Client add(
             final SAML2SP4UIIdP idp, final SAML2Configuration cfg, final 
String spEntityID, final String callbackUrl) {
 
-        cfg.setIdentityProviderMetadataResource((new 
ByteArrayResource(idp.getMetadata())));
+        cfg.setIdentityProviderEntityId(idp.getEntityID());
+        cfg.setIdentityProviderMetadataResource(new 
ByteArrayResource(idp.getMetadata()));
+        // remove when pac4j > 6.0.0-RC5 is available
+        cfg.setIdentityProviderMetadataResolver(new 
SAML2IdentityProviderMetadataResolver(cfg) {
+
+            private final AtomicBoolean hasChanged = new AtomicBoolean(true);
+
+            @Override
+            public boolean hasChanged() {
+                return hasChanged.getAndSet(false);
+            }
+        });
+
         cfg.setServiceProviderEntityId(spEntityID);
         
getSPMetadataPath(spEntityID).ifPresent(cfg::setServiceProviderMetadataResourceFilepath);
 
diff --git 
a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2SP4UIContext.java
 
b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2SP4UIContext.java
index 1722676508..834618401e 100644
--- 
a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2SP4UIContext.java
+++ 
b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2SP4UIContext.java
@@ -49,16 +49,14 @@ public class SAML2SP4UIContext implements WebContext {
 
     @Override
     public Optional<String> getRequestParameter(final String name) {
-        switch (name) {
-            case SAML2Constants.SAML_RESPONSE:
-                return Optional.ofNullable(saml2Response.getSamlResponse());
-
-            case SAML2Constants.RELAY_STATE:
-                return Optional.ofNullable(saml2Response.getRelayState());
-
-            default:
-                return Optional.empty();
-        }
+        return switch (name) {
+            case SAML2Constants.SAML_RESPONSE ->
+                Optional.ofNullable(saml2Response.getSamlResponse());
+            case SAML2Constants.RELAY_STATE ->
+                Optional.ofNullable(saml2Response.getRelayState());
+            default ->
+                Optional.empty();
+        };
     }
 
     @Override
diff --git a/fit/wa-reference/src/main/resources/log4j2.xml 
b/fit/wa-reference/src/main/resources/log4j2.xml
index 9254c8ecab..744d540e4c 100644
--- a/fit/wa-reference/src/main/resources/log4j2.xml
+++ b/fit/wa-reference/src/main/resources/log4j2.xml
@@ -39,6 +39,9 @@ under the License.
     <asyncLogger name="org.apereo.cas" additivity="false" level="INFO">
       <appender-ref ref="main"/>
     </asyncLogger>
+    <asyncLogger name="org.apereo.cas.support.saml.idp.metadata.generator" 
additivity="false" level="TRACE">
+      <appender-ref ref="main"/>
+    </asyncLogger>
 
     <asyncLogger name="org.apereo.services.persondir" additivity="false" 
level="INFO">
       <appender-ref ref="main"/>
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/SAML2SRAITCase.java 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/SAML2SRAITCase.java
index b96be4d323..d99e689221 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/SAML2SRAITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/SAML2SRAITCase.java
@@ -180,8 +180,7 @@ public class SAML2SRAITCase extends AbstractSRAITCase {
             post.setEntity(new UrlEncodedFormEntity(form, Consts.UTF_8));
             try (CloseableHttpResponse response = httpclient.execute(post, 
context)) {
                 assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, 
response.getStatusLine().getStatusCode());
-                location = 
response.getFirstHeader(HttpHeaders.LOCATION).getValue().
-                        replace("http://";, "https://";).replace(":8080", 
":9443");
+                location = 
response.getFirstHeader(HttpHeaders.LOCATION).getValue();
             }
         }
 
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
index fd37e60a1c..b7a38a7ad1 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
@@ -257,8 +257,7 @@ public class SAML2SP4UIITCase extends AbstractUIITCase {
             post.setEntity(new UrlEncodedFormEntity(form, Consts.UTF_8));
             try (CloseableHttpResponse response = httpclient.execute(post, 
context)) {
                 assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, 
response.getStatusLine().getStatusCode());
-                location = 
response.getFirstHeader(HttpHeaders.LOCATION).getValue().
-                        replace("http://";, "https://";).replace(":8080", 
":9443");
+                location = 
response.getFirstHeader(HttpHeaders.LOCATION).getValue();
             }
         }
 
diff --git a/pom.xml b/pom.xml
index 94901713ee..d853988d73 100644
--- a/pom.xml
+++ b/pom.xml
@@ -437,7 +437,7 @@ under the License.
 
     <modernizer-maven.version>2.5.0</modernizer-maven.version>
 
-    <pac4j.version>6.0.0-RC5-SNAPSHOT</pac4j.version>
+    <pac4j.version>6.0.0-RC5</pac4j.version>
 
     <cas.version>7.0.0-SNAPSHOT</cas.version>
     <cas-client.version>4.0.1</cas-client.version>
@@ -1687,7 +1687,7 @@ under the License.
             <dependency>
               <groupId>com.puppycrawl.tools</groupId>
               <artifactId>checkstyle</artifactId>
-              <version>10.6.0</version>
+              <version>10.7.0</version>
             </dependency>
           </dependencies>
           <configuration>
@@ -1749,7 +1749,7 @@ under the License.
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-enforcer-plugin</artifactId>
-        <version>3.1.0</version>
+        <version>3.2.1</version>
         <executions>
           <execution>
             <id>default-cli</id>
diff --git a/sra/src/main/java/org/apache/syncope/sra/SecurityConfig.java 
b/sra/src/main/java/org/apache/syncope/sra/SecurityConfig.java
index 8f69eccfe4..878ed14660 100644
--- a/sra/src/main/java/org/apache/syncope/sra/SecurityConfig.java
+++ b/sra/src/main/java/org/apache/syncope/sra/SecurityConfig.java
@@ -303,21 +303,19 @@ public class SecurityConfig {
                 anyExchange().authenticated();
 
         switch (props.getAmType()) {
-            case OIDC:
-            case OAUTH2:
+            case OIDC, OAUTH2 -> {
                 OAuth2SecurityConfigUtils.forLogin(http, props.getAmType(), 
ctx);
                 OAuth2SecurityConfigUtils.forLogout(builder, 
props.getAmType(), cacheManager, logoutRouteMatcher, ctx);
                 
http.oauth2ResourceServer().jwt().jwtDecoder(ctx.getBean(ReactiveJwtDecoder.class));
-                break;
+            }
 
-            case SAML2:
+            case SAML2 ->
                 saml2Client.ifAvailable(client -> {
                     SAML2SecurityConfigUtils.forLogin(http, client, 
publicRouteMatcher);
                     SAML2SecurityConfigUtils.forLogout(builder, client, 
cacheManager, logoutRouteMatcher, ctx);
                 });
-                break;
 
-            case CAS:
+            case CAS -> {
                 CASSecurityConfigUtils.forLogin(
                         http,
                         props.getCas().getProtocol(),
@@ -329,9 +327,10 @@ public class SecurityConfig {
                         props.getCas().getServerPrefix(),
                         logoutRouteMatcher,
                         ctx);
-                break;
+            }
 
-            default:
+            default -> {
+            }
         }
 
         return 
builder.and().csrf().requireCsrfProtectionMatcher(csrfRouteMatcher).and().build();
diff --git 
a/sra/src/main/java/org/apache/syncope/sra/security/pac4j/RedirectionActionUtils.java
 
b/sra/src/main/java/org/apache/syncope/sra/security/pac4j/RedirectionActionUtils.java
index c56c23f701..63cbc6a68a 100644
--- 
a/sra/src/main/java/org/apache/syncope/sra/security/pac4j/RedirectionActionUtils.java
+++ 
b/sra/src/main/java/org/apache/syncope/sra/security/pac4j/RedirectionActionUtils.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.sra.security.pac4j;
 
 import java.net.URI;
+import java.util.Optional;
 import org.pac4j.core.exception.http.RedirectionAction;
 import org.pac4j.core.exception.http.WithContentAction;
 import org.pac4j.core.exception.http.WithLocationAction;
@@ -32,27 +33,24 @@ public final class RedirectionActionUtils {
             final RedirectionAction action,
             final ServerWebExchangeContext swec) {
 
-        if (action instanceof WithLocationAction) {
-            WithLocationAction withLocationAction = (WithLocationAction) 
action;
+        if (action instanceof WithLocationAction withLocationAction) {
             swec.getNative().getResponse().setStatusCode(HttpStatus.FOUND);
             
swec.getNative().getResponse().getHeaders().setLocation(URI.create(withLocationAction.getLocation()));
             return swec.getNative().getResponse().setComplete();
-        } else if (action instanceof WithContentAction) {
-            WithContentAction withContentAction = (WithContentAction) action;
-            String content = withContentAction.getContent();
+        }
 
-            if (content == null) {
-                throw new IllegalArgumentException("No content set for POST 
AuthnRequest");
-            }
+        if (action instanceof WithContentAction withContentAction) {
+            String content = 
Optional.ofNullable(withContentAction.getContent()).
+                    orElseThrow(() -> new IllegalArgumentException("No content 
set for POST AuthnRequest"));
 
             return Mono.defer(() -> {
                 
swec.getNative().getResponse().getHeaders().setContentType(MediaType.TEXT_HTML);
                 return swec.getNative().getResponse().
                         
writeWith(Mono.just(swec.getNative().getResponse().bufferFactory().wrap(content.getBytes())));
             });
-        } else {
-            throw new IllegalArgumentException("Unsupported Action: " + 
action.getClass().getName());
         }
+
+        throw new IllegalArgumentException("Unsupported Action: " + 
action.getClass().getName());
     }
 
     private RedirectionActionUtils() {
diff --git 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2AuthenticationToken.java
 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2AuthenticationToken.java
index 74e712eb26..c99801dac7 100644
--- 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2AuthenticationToken.java
+++ 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2AuthenticationToken.java
@@ -18,9 +18,11 @@
  */
 package org.apache.syncope.sra.security.saml2;
 
+import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
-import org.pac4j.saml.credentials.SAML2Credentials;
+import org.pac4j.saml.credentials.SAML2AuthenticationCredentials;
 import org.springframework.security.authentication.AbstractAuthenticationToken;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 
@@ -28,11 +30,12 @@ public class SAML2AuthenticationToken extends 
AbstractAuthenticationToken {
 
     private static final long serialVersionUID = 8322987617416135717L;
 
-    private final SAML2Credentials credentials;
+    private final SAML2AuthenticationCredentials credentials;
 
-    public SAML2AuthenticationToken(final SAML2Credentials credentials) {
-        super(credentials.getUserProfile().getRoles().stream().
-                map(SimpleGrantedAuthority::new).collect(Collectors.toSet()));
+    public SAML2AuthenticationToken(final SAML2AuthenticationCredentials 
credentials) {
+        super(Optional.ofNullable(credentials.getUserProfile()).
+                map(p -> 
p.getRoles().stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet())).
+                orElse(Set.of()));
         this.credentials = credentials;
         this.setAuthenticated(true);
     }
@@ -43,7 +46,7 @@ public class SAML2AuthenticationToken extends 
AbstractAuthenticationToken {
     }
 
     @Override
-    public SAML2Credentials getPrincipal() {
+    public SAML2AuthenticationCredentials getPrincipal() {
         return credentials;
     }
 }
diff --git 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2LogoutResponseWebFilter.java
 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2LogoutResponseWebFilter.java
index 8d543159af..0f55618a88 100644
--- 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2LogoutResponseWebFilter.java
+++ 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2LogoutResponseWebFilter.java
@@ -18,21 +18,13 @@
  */
 package org.apache.syncope.sra.security.saml2;
 
-import java.util.Optional;
-import org.apache.syncope.sra.SessionConfig;
 import org.apache.syncope.sra.security.pac4j.NoOpSessionStore;
-import org.apache.syncope.sra.security.pac4j.RedirectionActionUtils;
 import org.apache.syncope.sra.security.pac4j.ServerWebExchangeContext;
 import org.pac4j.core.context.CallContext;
-import org.pac4j.core.exception.http.OkAction;
-import org.pac4j.core.exception.http.RedirectionAction;
-import org.pac4j.core.profile.factory.ProfileManagerFactory;
-import org.pac4j.core.util.Pac4jConstants;
+import org.pac4j.core.credentials.Credentials;
 import org.pac4j.saml.client.SAML2Client;
-import org.pac4j.saml.context.SAML2MessageContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.cache.CacheManager;
 import org.springframework.http.HttpMethod;
 import org.springframework.security.web.server.WebFilterExchange;
 import 
org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler;
@@ -51,46 +43,28 @@ public class SAML2LogoutResponseWebFilter implements 
WebFilter {
     public static final ServerWebExchangeMatcher MATCHER =
             ServerWebExchangeMatchers.pathMatchers("/logout/saml2/sso");
 
-    private static class ServerWebExchangeLogoutContext extends 
ServerWebExchangeContext {
-
-        ServerWebExchangeLogoutContext(final ServerWebExchange exchange) {
-            super(exchange);
-        }
-
-        @Override
-        public Optional<String> getRequestParameter(final String name) {
-            return Pac4jConstants.LOGOUT_ENDPOINT_PARAMETER.equals(name)
-                    ? Optional.of("true")
-                    : super.getRequestParameter(name);
-        }
-    }
-
     private final SAML2Client saml2Client;
 
     private final ServerLogoutSuccessHandler logoutSuccessHandler;
 
-    private final CacheManager cacheManager;
-
     public SAML2LogoutResponseWebFilter(
             final SAML2Client saml2Client,
-            final SAML2ServerLogoutSuccessHandler logoutSuccessHandler,
-            final CacheManager cacheManager) {
+            final SAML2ServerLogoutSuccessHandler logoutSuccessHandler) {
 
         this.saml2Client = saml2Client;
         this.logoutSuccessHandler = logoutSuccessHandler;
-        this.cacheManager = cacheManager;
     }
 
     private Mono<Void> handleLogoutResponse(
             final ServerWebExchange exchange, final WebFilterChain chain, 
final ServerWebExchangeContext swec) {
 
         try {
-            SAML2MessageContext ctx = 
saml2Client.getContextProvider().buildContext(
-                    new CallContext(swec, NoOpSessionStore.INSTANCE, 
ProfileManagerFactory.DEFAULT),
-                    this.saml2Client);
-            saml2Client.getLogoutProfileHandler().receive(ctx);
-        } catch (OkAction e) {
-            LOG.debug("LogoutResponse was actually validated but no 
postLogoutURL was set", e);
+            CallContext ctx = new CallContext(swec, NoOpSessionStore.INSTANCE);
+            Credentials creds = saml2Client.getCredentialsExtractor().
+                    extract(ctx).
+                    orElseThrow(() -> new IllegalStateException("Could not 
extract credentials"));
+
+            saml2Client.getLogoutProcessor().processLogout(ctx, creds);
         } catch (Exception e) {
             LOG.error("Could not validate LogoutResponse", e);
         }
@@ -98,47 +72,20 @@ public class SAML2LogoutResponseWebFilter implements 
WebFilter {
         return logoutSuccessHandler.onLogoutSuccess(new 
WebFilterExchange(exchange, chain), null);
     }
 
-    private Mono<Void> handleLogoutRequest(
-            final ServerWebExchange exchange, final WebFilterChain chain, 
final ServerWebExchangeContext swec) {
-
-        return exchange.getSession().
-                switchIfEmpty(chain.filter(exchange).then(Mono.empty())).
-                flatMap(session -> {
-                    
cacheManager.getCache(SessionConfig.DEFAULT_CACHE).evictIfPresent(session.getId());
-
-                    return session.invalidate().then(Mono.defer(() -> {
-                        try {
-                            saml2Client.getCredentialsExtractor().extract(new 
CallContext(
-                                    swec, NoOpSessionStore.INSTANCE, 
ProfileManagerFactory.DEFAULT));
-                        } catch (RedirectionAction action) {
-                            return RedirectionActionUtils.handle(action, swec);
-                        }
-
-                        return chain.filter(exchange).then(Mono.empty());
-                    }));
-                });
-    }
-
     private Mono<Void> handleGET(final ServerWebExchange exchange, final 
WebFilterChain chain) {
         if (exchange.getRequest().getQueryParams().getFirst("SAMLResponse") != 
null) {
             return handleLogoutResponse(exchange, chain, new 
ServerWebExchangeContext(exchange));
-        } else if 
(exchange.getRequest().getQueryParams().getFirst("SAMLRequest") != null) {
-            return handleLogoutRequest(exchange, chain, new 
ServerWebExchangeLogoutContext(exchange));
         }
 
         return chain.filter(exchange).then(Mono.empty());
     }
 
     private Mono<Void> handlePOST(final ServerWebExchange exchange, final 
WebFilterChain chain) {
-        return exchange.getFormData().flatMap(form -> {
-            if (form.containsKey("SAMLResponse")) {
-                return handleLogoutResponse(exchange, chain, new 
ServerWebExchangeContext(exchange).setForm(form));
-            } else if (form.containsKey("SAMLRequest")) {
-                return handleLogoutRequest(exchange, chain, new 
ServerWebExchangeLogoutContext(exchange).setForm(form));
-            }
-
-            return chain.filter(exchange).then(Mono.empty());
-        });
+        return exchange.getFormData().
+                filter(form -> form.containsKey("SAMLResponse")).
+                flatMap(form -> handleLogoutResponse(
+                exchange, chain, new 
ServerWebExchangeContext(exchange).setForm(form))).
+                or(chain.filter(exchange).then(Mono.empty()));
     }
 
     @Override
diff --git 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2RequestServerLogoutHandler.java
 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2RequestServerLogoutHandler.java
index 6854acb90c..57f5fcee80 100644
--- 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2RequestServerLogoutHandler.java
+++ 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2RequestServerLogoutHandler.java
@@ -23,9 +23,8 @@ import org.apache.syncope.sra.security.pac4j.NoOpSessionStore;
 import org.apache.syncope.sra.security.pac4j.RedirectionActionUtils;
 import org.apache.syncope.sra.security.pac4j.ServerWebExchangeContext;
 import org.pac4j.core.context.CallContext;
-import org.pac4j.core.profile.factory.ProfileManagerFactory;
 import org.pac4j.saml.client.SAML2Client;
-import org.pac4j.saml.credentials.SAML2Credentials;
+import org.pac4j.saml.credentials.SAML2AuthenticationCredentials;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.cache.CacheManager;
@@ -51,7 +50,8 @@ public class SAML2RequestServerLogoutHandler implements 
ServerLogoutHandler {
     public Mono<Void> logout(final WebFilterExchange exchange, final 
Authentication authentication) {
         return exchange.getExchange().getSession().
                 flatMap(session -> {
-                    SAML2Credentials credentials = (SAML2Credentials) 
authentication.getPrincipal();
+                    SAML2AuthenticationCredentials credentials = 
+                            (SAML2AuthenticationCredentials) 
authentication.getPrincipal();
 
                     LOG.debug("Creating SAML2 SP Logout Request for IDP[{}] 
and Profile[{}]",
                             saml2Client.getIdentityProviderResolvedEntityId(), 
credentials.getUserProfile());
@@ -60,9 +60,7 @@ public class SAML2RequestServerLogoutHandler implements 
ServerLogoutHandler {
 
                     
cacheManager.getCache(SessionConfig.DEFAULT_CACHE).evictIfPresent(session.getId());
                     return 
session.invalidate().then(saml2Client.getLogoutAction(
-                            new CallContext(swec, NoOpSessionStore.INSTANCE, 
ProfileManagerFactory.DEFAULT),
-                            credentials.getUserProfile(),
-                            null).
+                            new CallContext(swec, NoOpSessionStore.INSTANCE), 
credentials.getUserProfile(), null).
                             map(action -> 
RedirectionActionUtils.handle(action, swec)).
                             orElseThrow(() -> new IllegalStateException("No 
action generated")));
                 }).onErrorResume(Mono::error);
diff --git 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2SecurityConfigUtils.java
 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2SecurityConfigUtils.java
index a7be69c990..21b8923e8d 100644
--- 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2SecurityConfigUtils.java
+++ 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2SecurityConfigUtils.java
@@ -84,7 +84,7 @@ public final class SAML2SecurityConfigUtils {
                     SAML2ServerLogoutSuccessHandler.class);
 
             SAML2LogoutResponseWebFilter logoutResponseWebFilter =
-                    new SAML2LogoutResponseWebFilter(saml2Client, 
logoutSuccessHandler, cacheManager);
+                    new SAML2LogoutResponseWebFilter(saml2Client, 
logoutSuccessHandler);
             builder.and().addFilterAt(logoutResponseWebFilter, 
SecurityWebFiltersOrder.LOGOUT);
         } catch (ClassNotFoundException e) {
             LOG.error("While creating instance of {}", 
SAML2ServerLogoutSuccessHandler.class.getName(), e);
diff --git 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2WebSsoAuthenticationRequestWebFilter.java
 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2WebSsoAuthenticationRequestWebFilter.java
index a895ff299c..a504bc9711 100644
--- 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2WebSsoAuthenticationRequestWebFilter.java
+++ 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2WebSsoAuthenticationRequestWebFilter.java
@@ -18,11 +18,13 @@
  */
 package org.apache.syncope.sra.security.saml2;
 
+import java.net.URI;
 import org.apache.syncope.sra.security.pac4j.NoOpSessionStore;
 import org.apache.syncope.sra.security.pac4j.RedirectionActionUtils;
 import org.apache.syncope.sra.security.pac4j.ServerWebExchangeContext;
+import org.apache.syncope.sra.session.SessionUtils;
 import org.pac4j.core.context.CallContext;
-import org.pac4j.core.profile.factory.ProfileManagerFactory;
+import org.pac4j.core.util.generator.ValueGenerator;
 import org.pac4j.saml.client.SAML2Client;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -54,14 +56,23 @@ public class SAML2WebSsoAuthenticationRequestWebFilter 
implements WebFilter {
         return MATCHER.matches(exchange).
                 filter(MatchResult::isMatch).
                 switchIfEmpty(chain.filter(exchange).then(Mono.empty())).
-                flatMap(matchResult -> {
+                flatMap(r -> exchange.getSession()).
+                flatMap(session -> {
                     LOG.debug("Creating SAML2 SP Authentication Request for 
IDP[{}]",
                             saml2Client.getIdentityProviderResolvedEntityId());
 
+                    saml2Client.setStateGenerator(new ValueGenerator() {
+
+                        @Override
+                        public String generateValue(final CallContext ctx) {
+                            return 
session.<URI>getRequiredAttribute(SessionUtils.INITIAL_REQUEST_URI).toASCIIString();
+                        }
+                    });
+
                     ServerWebExchangeContext swec = new 
ServerWebExchangeContext(exchange);
 
                     return saml2Client.getRedirectionAction(
-                            new CallContext(swec, NoOpSessionStore.INSTANCE, 
ProfileManagerFactory.DEFAULT)).
+                            new CallContext(swec, NoOpSessionStore.INSTANCE)).
                             map(action -> 
RedirectionActionUtils.handle(action, swec)).
                             orElseThrow(() -> new IllegalStateException("No 
action generated"));
                 }).onErrorResume(Mono::error);
diff --git 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2WebSsoAuthenticationWebFilter.java
 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2WebSsoAuthenticationWebFilter.java
index a35e436f11..90f8346cce 100644
--- 
a/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2WebSsoAuthenticationWebFilter.java
+++ 
b/sra/src/main/java/org/apache/syncope/sra/security/saml2/SAML2WebSsoAuthenticationWebFilter.java
@@ -22,11 +22,10 @@ import java.net.URI;
 import org.apache.syncope.sra.security.pac4j.NoOpSessionStore;
 import org.apache.syncope.sra.security.pac4j.ServerWebExchangeContext;
 import 
org.apache.syncope.sra.security.web.server.DoNothingIfCommittedServerRedirectStrategy;
-import org.apache.syncope.sra.session.SessionUtils;
 import org.pac4j.core.context.CallContext;
-import org.pac4j.core.profile.factory.ProfileManagerFactory;
+import org.pac4j.core.credentials.Credentials;
 import org.pac4j.saml.client.SAML2Client;
-import org.pac4j.saml.credentials.SAML2Credentials;
+import org.pac4j.saml.credentials.SAML2AuthenticationCredentials;
 import 
org.springframework.security.authentication.ReactiveAuthenticationManager;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.web.server.ServerRedirectStrategy;
@@ -71,7 +70,7 @@ public class SAML2WebSsoAuthenticationWebFilter extends 
AuthenticationWebFilter
 
     private ServerWebExchangeMatcher matchSamlResponse() {
         return exchange -> exchange.getFormData().
-                filter(form -> form.containsKey("SAMLResponse")).
+                filter(form -> form.containsKey("SAMLResponse") && 
form.containsKey("RelayState")).
                 flatMap(form -> ServerWebExchangeMatcher.MatchResult.match()).
                 switchIfEmpty(ServerWebExchangeMatcher.MatchResult.notMatch());
     }
@@ -79,18 +78,19 @@ public class SAML2WebSsoAuthenticationWebFilter extends 
AuthenticationWebFilter
     private ServerAuthenticationConverter convertSamlResponse() {
         return exchange -> exchange.getFormData().
                 flatMap(form -> MATCHER.matches(exchange).
-                flatMap(matchResult -> {
+                flatMap(r -> {
                     ServerWebExchangeContext swec = new 
ServerWebExchangeContext(exchange).setForm(form);
+                    CallContext ctx = new CallContext(swec, 
NoOpSessionStore.INSTANCE);
 
-                    SAML2Credentials credentials = (SAML2Credentials) 
saml2Client.getCredentialsExtractor().
-                            extract(new CallContext(
-                                    swec, NoOpSessionStore.INSTANCE, 
ProfileManagerFactory.DEFAULT)).
-                            orElseThrow(() -> new IllegalStateException("No 
AuthnResponse found"));
+                    Credentials creds = saml2Client.getCredentialsExtractor().
+                            extract(ctx).
+                            orElseThrow(() -> new IllegalStateException("Could 
not extract credentials"));
 
-                    saml2Client.getAuthenticator().validate(
-                            new CallContext(swec, NoOpSessionStore.INSTANCE), 
credentials);
+                    SAML2AuthenticationCredentials authCreds = 
saml2Client.validateCredentials(ctx, creds).
+                            map(SAML2AuthenticationCredentials.class::cast).
+                            orElseThrow(() -> new 
IllegalArgumentException("Invalid SAML credentials provided"));
 
-                    return Mono.just(new 
SAML2AuthenticationToken(credentials));
+                    return Mono.just(new SAML2AuthenticationToken(authCreds));
                 }));
     }
 
@@ -103,10 +103,10 @@ public class SAML2WebSsoAuthenticationWebFilter extends 
AuthenticationWebFilter
             public Mono<Void> onAuthenticationSuccess(
                     final WebFilterExchange webFilterExchange, final 
Authentication authentication) {
 
-                return webFilterExchange.getExchange().getSession().
-                        flatMap(session -> this.redirectStrategy.sendRedirect(
+                return webFilterExchange.getExchange().getFormData().
+                        flatMap(form -> this.redirectStrategy.sendRedirect(
                         webFilterExchange.getExchange(),
-                        
session.<URI>getRequiredAttribute(SessionUtils.INITIAL_REQUEST_URI)));
+                        URI.create(form.get("RelayState").get(0))));
             }
         };
     }
diff --git a/sra/src/main/resources/sra.properties 
b/sra/src/main/resources/sra.properties
index 1e42d3efbc..ea56675260 100644
--- a/sra/src/main/resources/sra.properties
+++ b/sra/src/main/resources/sra.properties
@@ -23,6 +23,7 @@ server.port=8080
 management.endpoint.gateway.enabled=true
 
management.endpoints.web.exposure.include=info,health,loggers,metrics,gateway,sraSessions
 management.endpoint.health.show-details=ALWAYS
+management.endpoint.env.show-values=WHEN_AUTHORIZED
 spring.cloud.discovery.client.health-indicator.enabled=false
 
 service.discovery.address=http://localhost:8080/
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 9a91ba0260..feb0743019 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
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.wa.starter.config;
 
+import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
 import com.github.benmanes.caffeine.cache.LoadingCache;
 import com.warrenstrange.googleauth.IGoogleAuthenticator;
@@ -60,8 +61,9 @@ import 
org.apache.syncope.wa.starter.mapping.RegisteredServiceMapper;
 import org.apache.syncope.wa.starter.mapping.SAML2SPClientAppTOMapper;
 import org.apache.syncope.wa.starter.oidc.WAOIDCJWKSGeneratorService;
 import org.apache.syncope.wa.starter.pac4j.saml.WASAML2ClientCustomizer;
-import 
org.apache.syncope.wa.starter.saml.idp.metadata.RestfulSamlIdPMetadataGenerator;
-import 
org.apache.syncope.wa.starter.saml.idp.metadata.RestfulSamlIdPMetadataLocator;
+import org.apache.syncope.wa.starter.saml.idp.WASamlIdPCasEventListener;
+import 
org.apache.syncope.wa.starter.saml.idp.metadata.WASamlIdPMetadataGenerator;
+import 
org.apache.syncope.wa.starter.saml.idp.metadata.WASamlIdPMetadataLocator;
 import org.apache.syncope.wa.starter.services.WAServiceRegistry;
 import 
org.apache.syncope.wa.starter.surrogate.WASurrogateAuthenticationService;
 import org.apache.syncope.wa.starter.u2f.WAU2FDeviceRepository;
@@ -82,9 +84,11 @@ import org.apereo.cas.support.events.CasEventRepository;
 import org.apereo.cas.support.events.CasEventRepositoryFilter;
 import 
org.apereo.cas.support.pac4j.authentication.clients.DelegatedClientFactoryCustomizer;
 import 
org.apereo.cas.support.pac4j.authentication.handler.support.DelegatedClientAuthenticationHandler;
+import org.apereo.cas.support.saml.idp.SamlIdPCasEventListener;
 import 
org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGenerator;
 import 
org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGeneratorConfigurationContext;
 import org.apereo.cas.support.saml.idp.metadata.locator.SamlIdPMetadataLocator;
+import 
org.apereo.cas.support.saml.services.idp.metadata.SamlIdPMetadataDocument;
 import org.apereo.cas.util.DateTimeUtils;
 import org.apereo.cas.util.LdapUtils;
 import org.apereo.cas.util.crypto.CipherExecutor;
@@ -98,6 +102,7 @@ import 
org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.context.annotation.ScopedProxyMode;
 
 @Configuration(proxyBeanMethods = false)
@@ -221,36 +226,49 @@ public class WAContext {
     @Bean
     public ServiceRegistryExecutionPlanConfigurer 
syncopeServiceRegistryConfigurer(
             final ConfigurableApplicationContext ctx,
-            final WARestClient restClient,
+            final WARestClient waRestClient,
             final RegisteredServiceMapper registeredServiceMapper,
             @Qualifier("serviceRegistryListeners")
             final ObjectProvider<List<ServiceRegistryListener>> 
serviceRegistryListeners) {
 
         WAServiceRegistry registry = new WAServiceRegistry(
-                restClient, registeredServiceMapper, ctx,
+                waRestClient, registeredServiceMapper, ctx,
                 
Optional.ofNullable(serviceRegistryListeners.getIfAvailable()).orElseGet(ArrayList::new));
         return plan -> plan.registerServiceRegistry(registry);
     }
 
+    @Bean
+    @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
+    @Lazy(false)
+    public SamlIdPCasEventListener samlIdPCasEventListener() {
+        return new WASamlIdPCasEventListener();
+    }
+
     @Bean
     public SamlIdPMetadataGenerator samlIdPMetadataGenerator(
-            final WARestClient restClient,
+            final WARestClient waRestClient,
             final SamlIdPMetadataGeneratorConfigurationContext context) {
 
-        return new RestfulSamlIdPMetadataGenerator(context, restClient);
+        return new WASamlIdPMetadataGenerator(context, waRestClient);
     }
 
     @Bean
-    public SamlIdPMetadataLocator samlIdPMetadataLocator(final WARestClient 
restClient) {
-        return new RestfulSamlIdPMetadataLocator(
-                CipherExecutor.noOpOfStringToString(),
-                Caffeine.newBuilder().build(),
-                restClient);
+    public SamlIdPMetadataLocator samlIdPMetadataLocator(
+            @Qualifier("samlIdPMetadataGeneratorCipherExecutor")
+            final CipherExecutor<String, String> cipherExecutor,
+            @Qualifier("samlIdPMetadataCache")
+            final Cache<String, SamlIdPMetadataDocument> samlIdPMetadataCache,
+            final WARestClient waRestClient) {
+
+        return new WASamlIdPMetadataLocator(
+                cipherExecutor,
+                samlIdPMetadataCache,
+                waRestClient);
     }
 
     @Bean
-    public AuditTrailExecutionPlanConfigurer auditConfigurer(final 
WARestClient restClient) {
-        return plan -> plan.registerAuditTrailManager(new 
WAAuditTrailManager(restClient));
+    public AuditTrailExecutionPlanConfigurer auditConfigurer(final 
WARestClient waRestClient) {
+        return plan -> plan.registerAuditTrailManager(new 
WAAuditTrailManager(waRestClient));
     }
 
     @ConditionalOnMissingBean(name = "syncopeWAEventRepositoryFilter")
@@ -261,25 +279,25 @@ public class WAContext {
 
     @Bean
     public CasEventRepository casEventRepository(
-            final WARestClient restClient,
+            final WARestClient waRestClient,
             @Qualifier("syncopeWAEventRepositoryFilter")
             final CasEventRepositoryFilter syncopeWAEventRepositoryFilter) {
 
-        return new WAEventRepository(syncopeWAEventRepositoryFilter, 
restClient);
+        return new WAEventRepository(syncopeWAEventRepositoryFilter, 
waRestClient);
     }
 
     @Bean
-    public DelegatedClientFactoryCustomizer<Client> 
delegatedClientCustomizer(final WARestClient restClient) {
-        return new WASAML2ClientCustomizer(restClient);
+    public DelegatedClientFactoryCustomizer<Client> 
delegatedClientCustomizer(final WARestClient waRestClient) {
+        return new WASAML2ClientCustomizer(waRestClient);
     }
 
     @Bean
     public WAGoogleMfaAuthTokenRepository 
oneTimeTokenAuthenticatorTokenRepository(
             final CasConfigurationProperties casProperties,
-            final WARestClient restClient) {
+            final WARestClient waRestClient) {
 
         return new WAGoogleMfaAuthTokenRepository(
-                restClient, 
casProperties.getAuthn().getMfa().getGauth().getCore().getTimeStepSize());
+                waRestClient, 
casProperties.getAuthn().getMfa().getGauth().getCore().getTimeStepSize());
     }
 
     @ConditionalOnMissingBean(name = 
CUSTOM_GOOGLE_AUTHENTICATOR_ACCOUNT_REGISTRY)
@@ -292,7 +310,7 @@ public class WAContext {
             @Qualifier("googleAuthenticatorScratchCodesCipherExecutor")
             final CipherExecutor<Number, Number> 
googleAuthenticatorScratchCodesCipherExecutor,
             final IGoogleAuthenticator googleAuthenticatorInstance,
-            final WARestClient restClient) {
+            final WARestClient waRestClient) {
 
         /*
          * Declaring the LDAP-based repository as a Spring bean that would be 
conditionally activated
@@ -314,16 +332,16 @@ public class WAContext {
                     connectionFactory,
                     ldap);
         }
-        return new WAGoogleMfaAuthCredentialRepository(restClient, 
googleAuthenticatorInstance);
+        return new WAGoogleMfaAuthCredentialRepository(waRestClient, 
googleAuthenticatorInstance);
     }
 
     @Bean
     public OidcJsonWebKeystoreGeneratorService 
oidcJsonWebKeystoreGeneratorService(
             final CasConfigurationProperties casProperties,
-            final WARestClient restClient) {
+            final WARestClient waRestClient) {
 
         return new WAOIDCJWKSGeneratorService(
-                restClient,
+                waRestClient,
                 
casProperties.getAuthn().getOidc().getJwks().getCore().getJwksKeyId(),
                 
casProperties.getAuthn().getOidc().getJwks().getCore().getJwksType(),
                 
casProperties.getAuthn().getOidc().getJwks().getCore().getJwksKeySize());
@@ -332,15 +350,15 @@ public class WAContext {
     @Bean
     public WebAuthnCredentialRepository webAuthnCredentialRepository(
             final CasConfigurationProperties casProperties,
-            final WARestClient restClient) {
+            final WARestClient waRestClient) {
 
-        return new WAWebAuthnCredentialRepository(casProperties, restClient);
+        return new WAWebAuthnCredentialRepository(casProperties, waRestClient);
     }
 
     @Bean
     public U2FDeviceRepository u2fDeviceRepository(
             final CasConfigurationProperties casProperties,
-            final WARestClient restClient) {
+            final WARestClient waRestClient) {
 
         U2FCoreMultifactorAuthenticationProperties u2f = 
casProperties.getAuthn().getMfa().getU2f().getCore();
         OffsetDateTime expirationDate = OffsetDateTime.now().
@@ -348,18 +366,18 @@ public class WAContext {
         LoadingCache<String, String> requestStorage = Caffeine.newBuilder().
                 expireAfterWrite(u2f.getExpireRegistrations(), 
u2f.getExpireRegistrationsTimeUnit()).
                 build(key -> StringUtils.EMPTY);
-        return new WAU2FDeviceRepository(casProperties, requestStorage, 
restClient, expirationDate);
+        return new WAU2FDeviceRepository(casProperties, requestStorage, 
waRestClient, expirationDate);
     }
 
     @Bean
-    public SurrogateAuthenticationService surrogateAuthenticationService(final 
WARestClient restClient) {
-        return new WASurrogateAuthenticationService(restClient);
+    public SurrogateAuthenticationService surrogateAuthenticationService(final 
WARestClient waRestClient) {
+        return new WASurrogateAuthenticationService(waRestClient);
     }
 
     @ConditionalOnMissingBean
     @Bean
-    public SyncopeCoreHealthIndicator syncopeCoreHealthIndicator(final 
WARestClient restClient) {
-        return new SyncopeCoreHealthIndicator(restClient);
+    public SyncopeCoreHealthIndicator syncopeCoreHealthIndicator(final 
WARestClient waRestClient) {
+        return new SyncopeCoreHealthIndicator(waRestClient);
     }
 
     @ConditionalOnMissingBean
diff --git 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/JWSAlgorithm.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/WASamlIdPCasEventListener.java
similarity index 61%
rename from 
common/am/lib/src/main/java/org/apache/syncope/common/lib/types/JWSAlgorithm.java
rename to 
wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/WASamlIdPCasEventListener.java
index 015a9d2ec7..da1bcaf72c 100644
--- 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/JWSAlgorithm.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/WASamlIdPCasEventListener.java
@@ -16,22 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.common.lib.types;
+package org.apache.syncope.wa.starter.saml.idp;
 
-public enum JWSAlgorithm {
-    HS256,
-    HS384,
-    HS512,
-    RS256,
-    RS384,
-    RS512,
-    ES256,
-    ES384,
-    ES512,
-    PS256,
-    PS384,
-    PS512,
-    EdDSA,
-    ES256K;
+import org.apereo.cas.support.saml.idp.SamlIdPCasEventListener;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
 
+public class WASamlIdPCasEventListener implements SamlIdPCasEventListener {
+
+    @Override
+    public void handleApplicationReadyEvent(final ApplicationReadyEvent event) 
{
+        // skip generating IdP metadata at this stage, as
+        // org.apereo.cas.support.saml.idp.DefaultSamlIdPCasEventListener is 
doing
+    }
 }
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataGenerator.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataGenerator.java
similarity index 82%
rename from 
wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataGenerator.java
rename to 
wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataGenerator.java
index 2161f118ce..07a8227ee8 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataGenerator.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataGenerator.java
@@ -33,13 +33,13 @@ import 
org.apereo.cas.support.saml.services.idp.metadata.SamlIdPMetadataDocument
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class RestfulSamlIdPMetadataGenerator extends 
BaseSamlIdPMetadataGenerator {
+public class WASamlIdPMetadataGenerator extends BaseSamlIdPMetadataGenerator {
 
-    private static final Logger LOG = 
LoggerFactory.getLogger(RestfulSamlIdPMetadataGenerator.class);
+    private static final Logger LOG = 
LoggerFactory.getLogger(WASamlIdPMetadataGenerator.class);
 
     private final WARestClient waRestClient;
 
-    public RestfulSamlIdPMetadataGenerator(
+    public WASamlIdPMetadataGenerator(
             final SamlIdPMetadataGeneratorConfigurationContext 
samlIdPMetadataGeneratorConfigurationContext,
             final WARestClient waRestClient) {
 
@@ -47,14 +47,34 @@ public class RestfulSamlIdPMetadataGenerator extends 
BaseSamlIdPMetadataGenerato
         this.waRestClient = waRestClient;
     }
 
+    @Override
+    public String getAppliesToFor(final Optional<SamlRegisteredService> 
registeredService) {
+        return registeredService.
+                map(SamlRegisteredService::getName).
+                orElse(SAML2IdPEntityService.DEFAULT_OWNER);
+    }
+
+    private SyncopeClient getSyncopeClient() {
+        if (!waRestClient.isReady()) {
+            LOG.info("Syncope client is not yet ready");
+            throw new IllegalStateException("Syncope core is not yet ready to 
access requests");
+        }
+        return waRestClient.getSyncopeClient();
+    }
+
+    @Override
+    public SamlIdPMetadataDocument generate(final 
Optional<SamlRegisteredService> registeredService) throws Exception {
+        return super.generate(registeredService);
+    }
+
     @Override
     protected SamlIdPMetadataDocument finalizeMetadataDocument(
             final SamlIdPMetadataDocument doc,
             final Optional<SamlRegisteredService> registeredService) throws 
Exception {
 
-        LOG.info("Generating new SAML2 IdP metadata document");
+        doc.setAppliesTo(getAppliesToFor(registeredService));
 
-        doc.setAppliesTo(SAML2IdPEntityService.DEFAULT_OWNER);
+        LOG.info("Setting new SAML2 IdP metadata document for {}", 
doc.getAppliesTo());
 
         SAML2IdPEntityTO entityTO = new SAML2IdPEntityTO.Builder().
                 key(doc.getAppliesTo()).
@@ -84,23 +104,15 @@ public class RestfulSamlIdPMetadataGenerator extends 
BaseSamlIdPMetadataGenerato
 
     @Override
     public Pair<String, String> buildSelfSignedEncryptionCert(final 
Optional<SamlRegisteredService> registeredService)
-        throws Exception {
+            throws Exception {
 
         return generateCertificateAndKey();
     }
 
     @Override
     public Pair<String, String> buildSelfSignedSigningCert(final 
Optional<SamlRegisteredService> registeredService)
-        throws Exception {
+            throws Exception {
 
         return generateCertificateAndKey();
     }
-
-    private SyncopeClient getSyncopeClient() {
-        if (!waRestClient.isReady()) {
-            LOG.info("Syncope client is not yet ready");
-            throw new IllegalStateException("Syncope core is not yet ready to 
access requests");
-        }
-        return waRestClient.getSyncopeClient();
-    }
 }
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataLocator.java
similarity index 88%
rename from 
wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
rename to 
wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataLocator.java
index 71c8fa1d5e..fa490e195f 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataLocator.java
@@ -35,13 +35,13 @@ import org.apereo.cas.util.crypto.CipherExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class RestfulSamlIdPMetadataLocator extends 
AbstractSamlIdPMetadataLocator {
+public class WASamlIdPMetadataLocator extends AbstractSamlIdPMetadataLocator {
 
-    private static final Logger LOG = 
LoggerFactory.getLogger(RestfulSamlIdPMetadataLocator.class);
+    private static final Logger LOG = 
LoggerFactory.getLogger(WASamlIdPMetadataLocator.class);
 
     private final WARestClient waRestClient;
 
-    public RestfulSamlIdPMetadataLocator(
+    public WASamlIdPMetadataLocator(
             final CipherExecutor<String, String> metadataCipherExecutor,
             final Cache<String, SamlIdPMetadataDocument> metadataCache,
             final WARestClient waRestClient) {
@@ -50,6 +50,13 @@ public class RestfulSamlIdPMetadataLocator extends 
AbstractSamlIdPMetadataLocato
         this.waRestClient = waRestClient;
     }
 
+    @Override
+    public String getAppliesToFor(final Optional<SamlRegisteredService> 
registeredService) {
+        return registeredService.
+                map(SamlRegisteredService::getName).
+                orElse(SAML2IdPEntityService.DEFAULT_OWNER);
+    }
+
     @Override
     public SamlIdPMetadataDocument fetchInternal(final 
Optional<SamlRegisteredService> registeredService) {
         try {
@@ -94,7 +101,7 @@ public class RestfulSamlIdPMetadataLocator extends 
AbstractSamlIdPMetadataLocato
                 if (LOG.isDebugEnabled()) {
                     LOG.error("While fetching SAML2 IdP metadata", e);
                 } else {
-                    LOG.error("While fetching SAML2 IdP metadata: " + 
e.getMessage());
+                    LOG.error("While fetching SAML2 IdP metadata: {}", 
e.getMessage());
                 }
             }
         }
@@ -103,16 +110,14 @@ public class RestfulSamlIdPMetadataLocator extends 
AbstractSamlIdPMetadataLocato
     }
 
     private SAML2IdPEntityTO fetchFromCore(final 
Optional<SamlRegisteredService> registeredService) {
-        SAML2IdPEntityTO result = null;
+        SAML2IdPEntityService idpEntityService = 
getSyncopeClient().getService(SAML2IdPEntityService.class);
 
-        String appliesToFor = 
registeredService.map(SamlRegisteredService::getName).
-                orElse(SAML2IdPEntityService.DEFAULT_OWNER);
-        SAML2IdPEntityService service = 
getSyncopeClient().getService(SAML2IdPEntityService.class);
+        SAML2IdPEntityTO result = null;
         try {
-            result = service.get(appliesToFor);
+            result = idpEntityService.get(getAppliesToFor(registeredService));
         } catch (SyncopeClientException e) {
             if (e.getType() == ClientExceptionType.NotFound && 
registeredService.isPresent()) {
-                result = service.get(SAML2IdPEntityService.DEFAULT_OWNER);
+                result = 
idpEntityService.get(SAML2IdPEntityService.DEFAULT_OWNER);
             } else {
                 throw e;
             }
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/services/WAServiceRegistry.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/services/WAServiceRegistry.java
index 523be1164c..29665b7afe 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/services/WAServiceRegistry.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/services/WAServiceRegistry.java
@@ -20,6 +20,7 @@ package org.apache.syncope.wa.starter.services;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.types.ClientAppType;
@@ -142,14 +143,15 @@ public class WAServiceRegistry extends 
AbstractServiceRegistry {
 
     @Override
     public RegisteredService findServiceByExactServiceName(final String name) {
-        SyncopeClient syncopeClient = waRestClient.getSyncopeClient();
-        if (syncopeClient == null) {
-            LOG.debug("Syncope client is not yet ready to fetch application 
definitions");
-            return null;
-        } else {
-            LOG.info("Searching for application definition by name {}", name);
-            return 
registeredServiceMapper.toRegisteredService(waRestClient.getSyncopeClient().
-                    getService(WAClientAppService.class).read(name, null));
-        }
+        return Optional.ofNullable(waRestClient.getSyncopeClient()).
+                map(syncopeClient -> {
+                    LOG.info("Searching for application definition by name 
{}", name);
+                    return 
registeredServiceMapper.toRegisteredService(waRestClient.getSyncopeClient().
+                            getService(WAClientAppService.class).read(name, 
null));
+                }).
+                orElseGet(() -> {
+                    LOG.debug("Syncope client is not yet ready to fetch 
application definitions");
+                    return null;
+                });
     }
 }
diff --git a/wa/starter/src/main/resources/wa.properties 
b/wa/starter/src/main/resources/wa.properties
index 8d16065d89..7c8ccd378f 100644
--- a/wa/starter/src/main/resources/wa.properties
+++ b/wa/starter/src/main/resources/wa.properties
@@ -39,6 +39,7 @@ cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED
 management.endpoints.enabled-by-default=true
 
management.endpoints.web.exposure.include=info,health,env,loggers,ssoSessions,registeredServices,refresh,authenticationHandlers,authenticationPolicies,resolveAttributes
 management.endpoint.health.show-details=ALWAYS
+management.endpoint.env.show-values=WHEN_AUTHORIZED
 spring.cloud.discovery.client.health-indicator.enabled=false
 
 # Cache service definitions for 5 minutes

Reply via email to