This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch 4_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/4_0_X by this push:
new d2301197ef [SYNCOPE-1914] Multiple SAML 2.0 IdP support for WA (#1183)
d2301197ef is described below
commit d2301197ef87ef293f6a79301d35ba69029415a6
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Fri Sep 19 09:19:30 2025 +0200
[SYNCOPE-1914] Multiple SAML 2.0 IdP support for WA (#1183)
---
.../clientapps/ClientAppModalPanelBuilder.java | 14 ++++
.../apache/syncope/client/console/pages/WA.java | 6 +-
.../panels/SAML2IdPEntityDirectoryPanel.java | 89 +++++++++++++++++-----
.../console/rest/SAML2IdPEntityRestClient.java | 4 +
.../clientapps/ClientAppDirectoryPanel.properties | 1 +
.../ClientAppDirectoryPanel_fr_CA.properties | 1 +
.../ClientAppDirectoryPanel_it.properties | 1 +
.../ClientAppDirectoryPanel_ja.properties | 1 +
.../ClientAppDirectoryPanel_pt_BR.properties | 1 +
.../ClientAppDirectoryPanel_ru.properties | 1 +
.../syncope/common/lib/to/SAML2SPClientAppTO.java | 10 +++
.../syncope/common/lib/types/AMEntitlement.java | 2 +
.../rest/api/service/SAML2IdPEntityService.java | 15 +++-
.../syncope/core/logic/SAML2IdPEntityLogic.java | 9 ++-
.../cxf/service/SAML2IdPEntityServiceImpl.java | 5 ++
.../api/entity/am/SAML2SPClientApp.java | 5 ++
.../jpa/entity/am/JPASAML2SPClientApp.java | 13 ++++
.../neo4j/entity/am/Neo4jSAML2SPClientApp.java | 13 ++++
.../java/data/ClientAppDataBinderImpl.java | 22 ++++--
.../java/data/SAML2IdPEntityDataBinderImpl.java | 24 +++---
pom.xml | 13 +++-
.../syncope/wa/starter/config/WAContext.java | 19 ++++-
.../starter/mapping/SAML2SPClientAppTOMapper.java | 5 ++
.../metadata/WASamlIdPMetadataCacheRefresher.java | 45 +++++++++++
.../idp/metadata/WASamlIdPMetadataGenerator.java | 3 +-
.../idp/metadata/WASamlIdPMetadataLocator.java | 50 ++++++++----
wa/starter/src/main/resources/wa.properties | 2 +-
27 files changed, 308 insertions(+), 66 deletions(-)
diff --git
a/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/ClientAppModalPanelBuilder.java
b/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/ClientAppModalPanelBuilder.java
index 211ff1fce4..440d32d132 100644
---
a/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/ClientAppModalPanelBuilder.java
+++
b/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/ClientAppModalPanelBuilder.java
@@ -27,6 +27,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.RandomStringUtils;
@@ -59,6 +60,7 @@ import org.apache.syncope.common.lib.policy.PolicyTO;
import org.apache.syncope.common.lib.to.ClientAppTO;
import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.to.SAML2SPClientAppTO;
import org.apache.syncope.common.lib.types.ClientAppType;
import org.apache.syncope.common.lib.types.LogoutType;
import org.apache.syncope.common.lib.types.OIDCApplicationType;
@@ -72,6 +74,7 @@ import
org.apache.syncope.common.lib.types.OIDCTokenSigningAlg;
import org.apache.syncope.common.lib.types.PolicyType;
import org.apache.syncope.common.lib.types.SAML2SPNameId;
import org.apache.syncope.common.lib.types.XmlSecAlgorithm;
+import org.apache.syncope.common.rest.api.service.SAML2IdPEntityService;
import org.apache.wicket.Component;
import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -469,6 +472,17 @@ public class ClientAppModalPanelBuilder<T extends
ClientAppTO> extends AbstractM
"field", "entityId", new
PropertyModel<>(clientAppTO, "entityId"), false);
fields.add(entityId.setRequired(true));
+ fields.add(new AjaxTextFieldPanel("field", "idp", new
PropertyModel<>(clientAppTO, "idp") {
+
+ private static final long serialVersionUID =
-1476737401674143862L;
+
+ @Override
+ public String getObject() {
+ return Optional.ofNullable(((SAML2SPClientAppTO)
clientAppTO).getIdp()).
+
orElse(SAML2IdPEntityService.DEFAULT_OWNER);
+ }
+ }, false));
+
fields.add(new AjaxTextFieldPanel("field",
"metadataLocation",
new PropertyModel<>(clientAppTO,
"metadataLocation"), false).setRequired(true));
diff --git
a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java
b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java
index 58dda5ea16..39b0bd8562 100644
---
a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java
+++
b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java
@@ -45,6 +45,7 @@ import
org.apache.syncope.client.console.panels.WAPushModalPanel;
import org.apache.syncope.client.console.rest.AttrRepoRestClient;
import org.apache.syncope.client.console.rest.AuthModuleRestClient;
import org.apache.syncope.client.console.rest.AuthProfileRestClient;
+import org.apache.syncope.client.console.rest.ClientAppRestClient;
import org.apache.syncope.client.console.rest.SAML2IdPEntityRestClient;
import org.apache.syncope.client.console.rest.WAConfigRestClient;
import org.apache.syncope.client.console.rest.WASessionRestClient;
@@ -87,6 +88,9 @@ public class WA extends BasePage {
@SpringBean
protected SAML2IdPEntityRestClient saml2IdPEntityRestClient;
+ @SpringBean
+ protected ClientAppRestClient clientAppRestClient;
+
@SpringBean
protected ServiceOps serviceOps;
@@ -210,7 +214,7 @@ public class WA extends BasePage {
@Override
public Panel getPanel(final String panelId) {
return new SAML2IdPEntityDirectoryPanel(
- panelId, saml2IdPEntityRestClient, waPrefix,
getPageReference());
+ panelId, saml2IdPEntityRestClient,
clientAppRestClient, waPrefix, getPageReference());
}
});
diff --git
a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SAML2IdPEntityDirectoryPanel.java
b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SAML2IdPEntityDirectoryPanel.java
index 2ec1e9ea21..735d7cc99b 100644
---
a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SAML2IdPEntityDirectoryPanel.java
+++
b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/SAML2IdPEntityDirectoryPanel.java
@@ -23,18 +23,25 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
import org.apache.syncope.client.console.commons.AMConstants;
import org.apache.syncope.client.console.commons.DirectoryDataProvider;
import
org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.pages.BasePage;
import
org.apache.syncope.client.console.panels.SAML2IdPEntityDirectoryPanel.SAML2IdPEntityProvider;
+import org.apache.syncope.client.console.rest.ClientAppRestClient;
import org.apache.syncope.client.console.rest.SAML2IdPEntityRestClient;
import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
import org.apache.syncope.client.console.wizards.SAML2IdPEntityWizardBuilder;
import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.to.SAML2IdPEntityTO;
+import org.apache.syncope.common.lib.to.SAML2SPClientAppTO;
import org.apache.syncope.common.lib.types.AMEntitlement;
+import org.apache.syncope.common.lib.types.ClientAppType;
+import org.apache.syncope.common.rest.api.service.SAML2IdPEntityService;
import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.event.Broadcast;
@@ -43,10 +50,12 @@ import
org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColu
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import
org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
@@ -55,15 +64,47 @@ public class SAML2IdPEntityDirectoryPanel extends
DirectoryPanel<
private static final long serialVersionUID = -6535332920023200166L;
+ private static ExternalLink metadataLink(final String componentId, final
String url) {
+ return new ExternalLink(componentId, Model.of(url), Model.of(url)) {
+
+ private static final long serialVersionUID = -1919646533527005367L;
+
+ @Override
+ protected void onComponentTag(final ComponentTag tag) {
+ super.onComponentTag(tag);
+
+ tag.setName("a");
+ if (url.startsWith("http")) {
+ tag.put("href", getDefaultModelObject().toString());
+ tag.put("target", "_blank");
+ }
+ }
+ };
+ }
+
+ private final LoadableDetachableModel<List<SAML2SPClientAppTO>> clientApps;
+
private final String metadataURL;
public SAML2IdPEntityDirectoryPanel(
final String id,
final SAML2IdPEntityRestClient restClient,
+ final ClientAppRestClient clientAppRestClient,
final String waPrefix,
final PageReference pageRef) {
super(id, restClient, pageRef);
+
+ clientApps = new LoadableDetachableModel<>() {
+
+ private static final long serialVersionUID = 7172461137064525667L;
+
+ @Override
+ protected List<SAML2SPClientAppTO> load() {
+ return clientAppRestClient.list(ClientAppType.SAML2SP);
+ }
+ };
+
this.metadataURL = waPrefix + "/idp/metadata";
disableCheckBoxes();
@@ -98,24 +139,16 @@ public class SAML2IdPEntityDirectoryPanel extends
DirectoryPanel<
final String componentId,
final IModel<SAML2IdPEntityTO> rowModel) {
- cellItem.add(new ExternalLink(
- componentId,
- Model.of(metadataURL),
- Model.of(metadataURL)) {
-
- private static final long serialVersionUID =
-1919646533527005367L;
-
- @Override
- protected void onComponentTag(final ComponentTag tag) {
- super.onComponentTag(tag);
-
- tag.setName("a");
- if (metadataURL.startsWith("http")) {
- tag.put("href",
getDefaultModelObject().toString());
- tag.put("target", "_blank");
- }
- }
- });
+ if
(SAML2IdPEntityService.DEFAULT_OWNER.equals(rowModel.getObject().getKey())) {
+ cellItem.add(metadataLink(componentId, metadataURL));
+ } else {
+ clientApps.getObject().stream().
+ filter(app ->
rowModel.getObject().getKey().equals(app.getIdp())).
+ findFirst().ifPresentOrElse(
+ app -> cellItem.add(metadataLink(
+ componentId, metadataURL +
"?service=" + app.getClientAppId())),
+ () -> cellItem.add(new Label(componentId,
Model.of())));
+ }
}
});
@@ -138,6 +171,26 @@ public class SAML2IdPEntityDirectoryPanel extends
DirectoryPanel<
}
}, ActionLink.ActionType.EDIT, AMEntitlement.SAML2_IDP_ENTITY_SET);
+ if
(!SAML2IdPEntityService.DEFAULT_OWNER.equals(model.getObject().getKey())) {
+ panel.add(new ActionLink<>() {
+
+ private static final long serialVersionUID =
-3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target, final
SAML2IdPEntityTO ignore) {
+ try {
+ restClient.delete(model.getObject().getKey());
+
SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
+ target.add(container);
+ } catch (SyncopeClientException e) {
+ LOG.error("While deleting IdP {}",
model.getObject().getKey(), e);
+ SyncopeConsoleSession.get().onException(e);
+ }
+ ((BasePage)
pageRef.getPage()).getNotificationPanel().refresh(target);
+ }
+ }, ActionLink.ActionType.DELETE,
AMEntitlement.SAML2_IDP_ENTITY_DELETE, true);
+ }
+
return panel;
}
diff --git
a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/SAML2IdPEntityRestClient.java
b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/SAML2IdPEntityRestClient.java
index 9c66b1e784..26b7a13c36 100644
---
a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/SAML2IdPEntityRestClient.java
+++
b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/SAML2IdPEntityRestClient.java
@@ -38,4 +38,8 @@ public class SAML2IdPEntityRestClient extends BaseRestClient {
public void set(final SAML2IdPEntityTO entityTO) {
getService(SAML2IdPEntityService.class).set(entityTO);
}
+
+ public void delete(final String key) {
+ getService(SAML2IdPEntityService.class).delete(key);
+ }
}
diff --git
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel.properties
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel.properties
index 229c25a262..e3ba1847eb 100644
---
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel.properties
+++
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel.properties
@@ -81,3 +81,4 @@ userInfoSigningAlg=UserInfo Signing Algorithm
userInfoEncryptedResponseAlg=UserInfo Encrypted Response Algorithm
userInfoEncryptedResponseEncoding=UserInfo Encrypted Response Encoding
evaluationOrder=Evaluation Order
+idp=Identity Provider
diff --git
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_fr_CA.properties
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_fr_CA.properties
index b8f5fc8798..2bb0a441b3 100644
---
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_fr_CA.properties
+++
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_fr_CA.properties
@@ -81,3 +81,4 @@ userInfoSigningAlg=UserInfo Signing Algorithm
userInfoEncryptedResponseAlg=UserInfo Encrypted Response Algorithm
userInfoEncryptedResponseEncoding=UserInfo Encrypted Response Encoding
evaluationOrder=Evaluation Order
+idp=Identity Provider
diff --git
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_it.properties
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_it.properties
index 90bfaf968a..2ad1b0f69b 100644
---
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_it.properties
+++
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_it.properties
@@ -81,3 +81,4 @@ userInfoSigningAlg=Algoritmo di firma UserInfo
userInfoEncryptedResponseAlg=Algoritmo di cifratura risposta UserInfo
userInfoEncryptedResponseEncoding=Codifica di cifratura risposta UserInfo
evaluationOrder=Ordine di valutazione
+idp=Identity Provider
diff --git
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_ja.properties
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_ja.properties
index 428c4dce87..d0868ef9f2 100644
---
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_ja.properties
+++
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_ja.properties
@@ -81,3 +81,4 @@ userInfoSigningAlg=UserInfo Signing Algorithm
userInfoEncryptedResponseAlg=UserInfo Encrypted Response Algorithm
userInfoEncryptedResponseEncoding=UserInfo Encrypted Response Encoding
evaluationOrder=Evaluation Order
+idp=Identity Provider
diff --git
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_pt_BR.properties
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_pt_BR.properties
index 5438363123..1bd4e93e86 100644
---
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_pt_BR.properties
+++
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_pt_BR.properties
@@ -81,3 +81,4 @@ userInfoSigningAlg=UserInfo Signing Algorithm
userInfoEncryptedResponseAlg=UserInfo Encrypted Response Algorithm
userInfoEncryptedResponseEncoding=UserInfo Encrypted Response Encoding
evaluationOrder=Evaluation Order
+idp=Identity Provider
diff --git
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_ru.properties
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_ru.properties
index 09307c8825..bc0ab53d9d 100644
---
a/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_ru.properties
+++
b/client/am/console/src/main/resources/org/apache/syncope/client/console/clientapps/ClientAppDirectoryPanel_ru.properties
@@ -82,3 +82,4 @@ userInfoSigningAlg=UserInfo Signing Algorithm
userInfoEncryptedResponseAlg=UserInfo Encrypted Response Algorithm
userInfoEncryptedResponseEncoding=UserInfo Encrypted Response Encoding
evaluationOrder=Evaluation Order
+idp=Identity Provider
diff --git
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/SAML2SPClientAppTO.java
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/SAML2SPClientAppTO.java
index 7887bbcd21..46ad7f5384 100644
---
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/SAML2SPClientAppTO.java
+++
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/SAML2SPClientAppTO.java
@@ -36,6 +36,8 @@ public class SAML2SPClientAppTO extends ClientAppTO {
private String entityId;
+ private String idp;
+
private String metadataLocation;
private String metadataSignatureLocation;
@@ -89,6 +91,14 @@ public class SAML2SPClientAppTO extends ClientAppTO {
this.entityId = entityId;
}
+ public String getIdp() {
+ return idp;
+ }
+
+ public void setIdp(final String idp) {
+ this.idp = idp;
+ }
+
public String getMetadataLocation() {
return metadataLocation;
}
diff --git
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java
index ceae04b368..f9fd0d6508 100644
---
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java
+++
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java
@@ -74,6 +74,8 @@ public final class AMEntitlement {
public static final String SAML2_IDP_ENTITY_GET = "SAML2_IDP_ENTITY_GET";
+ public static final String SAML2_IDP_ENTITY_DELETE =
"SAML2_IDP_ENTITY_DELETE";
+
public static final String AUTH_PROFILE_DELETE = "AUTH_PROFILE_DELETE";
public static final String AUTH_PROFILE_CREATE = "AUTH_PROFILE_CREATE";
diff --git
a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPEntityService.java
b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPEntityService.java
index 47979cfa27..c13b48b999 100644
---
a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPEntityService.java
+++
b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPEntityService.java
@@ -26,6 +26,7 @@ import
io.swagger.v3.oas.annotations.security.SecurityRequirements;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
@@ -69,7 +70,7 @@ public interface SAML2IdPEntityService extends JAXRSService {
SAML2IdPEntityTO get(@NotNull @PathParam("key") String key);
/**
- * Store the entity to finalize the generation process.
+ * Stores the entity to finalize the generation process.
*
* @param entityTO entity to be created
*/
@@ -80,4 +81,16 @@ public interface SAML2IdPEntityService extends JAXRSService {
@Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML,
MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML,
MediaType.APPLICATION_XML })
void set(@NotNull SAML2IdPEntityTO entityTO);
+
+ /**
+ * Deletes the SAML 2.0 IdP entity matching the given key.
+ *
+ * @param key key of requested SAML 2.0 IdP entity
+ */
+ @Parameter(name = "key", description = "SAML2IdPEntityTO's key", in =
ParameterIn.PATH, schema =
+ @Schema(type = "string"))
+ @DELETE
+ @Path("{key}")
+ @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML,
MediaType.APPLICATION_XML })
+ void delete(@NotNull @PathParam("key") String key);
}
diff --git
a/core/am/logic/src/main/java/org/apache/syncope/core/logic/SAML2IdPEntityLogic.java
b/core/am/logic/src/main/java/org/apache/syncope/core/logic/SAML2IdPEntityLogic.java
index cc50248f79..243c00eebb 100644
---
a/core/am/logic/src/main/java/org/apache/syncope/core/logic/SAML2IdPEntityLogic.java
+++
b/core/am/logic/src/main/java/org/apache/syncope/core/logic/SAML2IdPEntityLogic.java
@@ -68,6 +68,11 @@ public class SAML2IdPEntityLogic extends
AbstractTransactionalLogic<SAML2IdPEnti
return binder.getSAML2IdPEntityTO(saml2IdPEntityDAO.save(entity));
}
+ @PreAuthorize("hasRole('" + AMEntitlement.SAML2_IDP_ENTITY_DELETE + "')")
+ public void delete(final String key) {
+ saml2IdPEntityDAO.deleteById(key);
+ }
+
@Override
protected SAML2IdPEntityTO resolveReference(final Method method, final
Object... args)
throws UnresolvedReferenceException {
@@ -77,8 +82,8 @@ public class SAML2IdPEntityLogic extends
AbstractTransactionalLogic<SAML2IdPEnti
for (int i = 0; key == null && i < args.length; i++) {
if (args[i] instanceof String string) {
key = string;
- } else if (args[i] instanceof SAML2IdPEntityTO
sAML2IdPEntityTO) {
- key = sAML2IdPEntityTO.getKey();
+ } else if (args[i] instanceof SAML2IdPEntityTO idp) {
+ key = idp.getKey();
}
}
}
diff --git
a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPEntityServiceImpl.java
b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPEntityServiceImpl.java
index 45050ecea7..94a4566dd1 100644
---
a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPEntityServiceImpl.java
+++
b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPEntityServiceImpl.java
@@ -45,4 +45,9 @@ public class SAML2IdPEntityServiceImpl extends
AbstractService implements SAML2I
public void set(final SAML2IdPEntityTO entityTO) {
logic.set(entityTO);
}
+
+ @Override
+ public void delete(final String key) {
+ logic.delete(key);
+ }
}
diff --git
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/SAML2SPClientApp.java
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/SAML2SPClientApp.java
index 608b0c2762..caf8d8a143 100644
---
a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/SAML2SPClientApp.java
+++
b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/SAML2SPClientApp.java
@@ -19,6 +19,7 @@
package org.apache.syncope.core.persistence.api.entity.am;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import org.apache.syncope.common.lib.types.SAML2SPNameId;
import org.apache.syncope.common.lib.types.XmlSecAlgorithm;
@@ -29,6 +30,10 @@ public interface SAML2SPClientApp extends ClientApp {
void setEntityId(String id);
+ Optional<String> getIdp();
+
+ void setIdp(String idp);
+
String getMetadataLocation();
void setMetadataLocation(String location);
diff --git
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPASAML2SPClientApp.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPASAML2SPClientApp.java
index 6512f7d3bf..af6c17c937 100644
---
a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPASAML2SPClientApp.java
+++
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPASAML2SPClientApp.java
@@ -32,6 +32,7 @@ import jakarta.persistence.Transient;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import org.apache.syncope.common.lib.types.SAML2SPNameId;
import org.apache.syncope.common.lib.types.XmlSecAlgorithm;
@@ -56,6 +57,8 @@ public class JPASAML2SPClientApp extends AbstractClientApp
implements SAML2SPCli
@Column(unique = true, nullable = false)
private String entityId;
+ private String idp;
+
@Column(nullable = false)
private String metadataLocation;
@@ -139,6 +142,16 @@ public class JPASAML2SPClientApp extends AbstractClientApp
implements SAML2SPCli
this.entityId = entityId;
}
+ @Override
+ public Optional<String> getIdp() {
+ return Optional.ofNullable(idp);
+ }
+
+ @Override
+ public void setIdp(final String idp) {
+ this.idp = idp;
+ }
+
@Override
public String getMetadataLocation() {
return metadataLocation;
diff --git
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jSAML2SPClientApp.java
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jSAML2SPClientApp.java
index 17ea8b8b18..3c6902bfd7 100644
---
a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jSAML2SPClientApp.java
+++
b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jSAML2SPClientApp.java
@@ -23,6 +23,7 @@ import jakarta.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import org.apache.syncope.common.lib.types.SAML2SPNameId;
import org.apache.syncope.common.lib.types.XmlSecAlgorithm;
@@ -49,6 +50,8 @@ public class Neo4jSAML2SPClientApp extends AbstractClientApp
implements SAML2SPC
@NotNull
private String entityId;
+ private String idp;
+
private String metadataLocation;
private String metadataSignatureLocation;
@@ -116,6 +119,16 @@ public class Neo4jSAML2SPClientApp extends
AbstractClientApp implements SAML2SPC
this.entityId = entityId;
}
+ @Override
+ public Optional<String> getIdp() {
+ return Optional.ofNullable(idp);
+ }
+
+ @Override
+ public void setIdp(final String idp) {
+ this.idp = idp;
+ }
+
@Override
public String getMetadataLocation() {
return metadataLocation;
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ClientAppDataBinderImpl.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ClientAppDataBinderImpl.java
index dcb6a84971..7eed004751 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ClientAppDataBinderImpl.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ClientAppDataBinderImpl.java
@@ -25,6 +25,7 @@ import org.apache.syncope.common.lib.to.ClientAppTO;
import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
import org.apache.syncope.common.lib.to.SAML2SPClientAppTO;
import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.rest.api.service.SAML2IdPEntityService;
import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
import org.apache.syncope.core.persistence.api.dao.RealmSearchDAO;
import org.apache.syncope.core.persistence.api.entity.EntityFactory;
@@ -76,14 +77,15 @@ public class ClientAppDataBinderImpl implements
ClientAppDataBinder {
@Override
public <T extends ClientApp> void update(final T clientApp, final
ClientAppTO clientAppTO) {
- if (clientAppTO instanceof SAML2SPClientAppTO sAML2SPClientAppTO) {
- doUpdate((SAML2SPClientApp) clientApp, sAML2SPClientAppTO);
- } else if (clientAppTO instanceof OIDCRPClientAppTO oIDCRPClientAppTO)
{
- doUpdate((OIDCRPClientApp) clientApp, oIDCRPClientAppTO);
- } else if (clientAppTO instanceof CASSPClientAppTO cASSPClientAppTO) {
- doUpdate((CASSPClientApp) clientApp, cASSPClientAppTO);
- } else {
- throw new IllegalArgumentException("Unsupported client app: " +
clientAppTO.getClass().getName());
+ switch (clientAppTO) {
+ case SAML2SPClientAppTO saml2sp ->
+ doUpdate((SAML2SPClientApp) clientApp, saml2sp);
+ case OIDCRPClientAppTO oidcrp ->
+ doUpdate((OIDCRPClientApp) clientApp, oidcrp);
+ case CASSPClientAppTO cassp ->
+ doUpdate((CASSPClientApp) clientApp, cassp);
+ default ->
+ throw new IllegalArgumentException("Unsupported client app: "
+ clientAppTO.getClass().getName());
}
}
@@ -118,6 +120,9 @@ public class ClientAppDataBinderImpl implements
ClientAppDataBinder {
copyToEntity(clientApp, clientAppTO);
clientApp.setEntityId(clientAppTO.getEntityId());
+ if (clientAppTO.getIdp() != null &&
!SAML2IdPEntityService.DEFAULT_OWNER.equals(clientAppTO.getIdp())) {
+ clientApp.setIdp(clientAppTO.getIdp());
+ }
clientApp.setMetadataLocation(clientAppTO.getMetadataLocation());
clientApp.setMetadataSignatureLocation(clientAppTO.getMetadataSignatureLocation());
clientApp.setSignAssertions(clientAppTO.isSignAssertions());
@@ -183,6 +188,7 @@ public class ClientAppDataBinderImpl implements
ClientAppDataBinder {
SAML2SPClientAppTO clientAppTO = new SAML2SPClientAppTO();
copyToTO(clientApp, clientAppTO);
+ clientAppTO.setIdp(clientApp.getIdp().orElse(null));
clientAppTO.setEntityId(clientApp.getEntityId());
clientAppTO.setMetadataLocation(clientApp.getMetadataLocation());
clientAppTO.setMetadataSignatureLocation(clientApp.getMetadataSignatureLocation());
diff --git
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPEntityDataBinderImpl.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPEntityDataBinderImpl.java
index af43b597fb..516dcbf7d3 100644
---
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPEntityDataBinderImpl.java
+++
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPEntityDataBinderImpl.java
@@ -19,6 +19,7 @@
package org.apache.syncope.core.provisioning.java.data;
import java.util.Base64;
+import java.util.Optional;
import org.apache.syncope.common.lib.to.SAML2IdPEntityTO;
import org.apache.syncope.core.persistence.api.entity.EntityFactory;
import org.apache.syncope.core.persistence.api.entity.am.SAML2IdPEntity;
@@ -64,21 +65,14 @@ public class SAML2IdPEntityDataBinderImpl implements
SAML2IdPEntityDataBinder {
SAML2IdPEntityTO entityTO = new SAML2IdPEntityTO();
entityTO.setKey(entity.getKey());
entityTO.setMetadata(Base64.getEncoder().encodeToString(entity.getMetadata()));
- if (entity.getEncryptionCertificate() != null) {
- entityTO.setEncryptionCertificate(
-
Base64.getEncoder().encodeToString(entity.getEncryptionCertificate()));
- }
- if (entity.getEncryptionKey() != null) {
- entityTO.setEncryptionKey(
-
Base64.getEncoder().encodeToString(entity.getEncryptionKey()));
- }
- if (entity.getSigningCertificate() != null) {
- entityTO.setSigningCertificate(
-
Base64.getEncoder().encodeToString(entity.getSigningCertificate()));
- }
- if (entity.getSigningKey() != null) {
-
entityTO.setSigningKey(Base64.getEncoder().encodeToString(entity.getSigningKey()));
- }
+ Optional.ofNullable(entity.getEncryptionCertificate()).
+ ifPresent(cert ->
entityTO.setEncryptionCertificate(Base64.getEncoder().encodeToString(cert)));
+ Optional.ofNullable(entity.getEncryptionKey()).
+ ifPresent(key ->
entityTO.setEncryptionKey(Base64.getEncoder().encodeToString(key)));
+ Optional.ofNullable(entity.getSigningCertificate()).
+ ifPresent(cert ->
entityTO.setSigningCertificate(Base64.getEncoder().encodeToString(cert)));
+ Optional.ofNullable(entity.getSigningKey()).
+ ifPresent(key ->
entityTO.setSigningKey(Base64.getEncoder().encodeToString(key)));
return entityTO;
}
}
diff --git a/pom.xml b/pom.xml
index e3609040cf..c563c2ecd8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -415,7 +415,7 @@ under the License.
<bouncycastle.version>1.81</bouncycastle.version>
<nimbus-jose-jwt.version>10.5</nimbus-jose-jwt.version>
- <spring-boot.version>3.4.9</spring-boot.version>
+ <spring-boot.version>3.4.10</spring-boot.version>
<spring-cloud-gateway.version>4.2.5</spring-cloud-gateway.version>
<openjpa.version>4.1.1</openjpa.version>
@@ -429,7 +429,7 @@ under the License.
<disruptor.version>4.0.0</disruptor.version>
- <elasticsearch.version>9.1.3</elasticsearch.version>
+ <elasticsearch.version>9.1.4</elasticsearch.version>
<opensearch.version>3.2.0</opensearch.version>
<opensearch-java.version>3.2.0</opensearch-java.version>
@@ -446,7 +446,7 @@ under the License.
<cas.version>7.2.6</cas.version>
<cas-client.version>4.0.4</cas-client.version>
- <swagger-core.version>2.2.36</swagger-core.version>
+ <swagger-core.version>2.2.37</swagger-core.version>
<swagger-ui.version>5.28.0</swagger-ui.version>
<jquery-slimscroll.version>1.3.8</jquery-slimscroll.version>
@@ -984,6 +984,11 @@ under the License.
<artifactId>groovy-groovysh</artifactId>
<version>${groovy.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.groovy</groupId>
+ <artifactId>groovy-nio</artifactId>
+ <version>${groovy.version}</version>
+ </dependency>
<dependency>
<groupId>net.tirasa</groupId>
@@ -1700,7 +1705,7 @@ under the License.
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
- <version>7.14.0</version>
+ <version>7.15.0</version>
</plugin>
<plugin>
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 77a8240a4a..7ce97dcf7e 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
@@ -19,6 +19,7 @@
package org.apache.syncope.wa.starter.config;
import com.github.benmanes.caffeine.cache.Cache;
+import com.github.benmanes.caffeine.cache.Caffeine;
import com.warrenstrange.googleauth.IGoogleAuthenticator;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
@@ -60,6 +61,7 @@ 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.pac4j.saml.WASAML2ClientCustomizer;
+import
org.apache.syncope.wa.starter.saml.idp.metadata.WASamlIdPMetadataCacheRefresher;
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;
@@ -210,7 +212,7 @@ public class WAContext {
return new RegisteredServiceMapper(
Optional.ofNullable(casProperties.getAuthn().getPac4j().getCore().getName()).
-
orElseGet(DelegatedClientAuthenticationHandler.class::getSimpleName),
+
orElseGet(DelegatedClientAuthenticationHandler.class::getSimpleName),
authenticationEventExecutionPlan,
multifactorAuthenticationProviders,
authMappers,
@@ -251,6 +253,12 @@ public class WAContext {
return new WASamlIdPMetadataGenerator(context, waRestClient);
}
+ @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
+ @Bean
+ public Cache<String, SamlIdPMetadataDocument> samlIdPMetadataCache() {
+ return Caffeine.newBuilder().build();
+ }
+
@Bean
public SamlIdPMetadataLocator samlIdPMetadataLocator(
@Qualifier("samlIdPMetadataGeneratorCipherExecutor")
@@ -267,6 +275,15 @@ public class WAContext {
waRestClient);
}
+ @ConditionalOnMissingBean
+ @Bean
+ public WASamlIdPMetadataCacheRefresher samlIdPMetadataCacheRefresher(
+ @Qualifier("samlIdPMetadataCache")
+ final Cache<String, SamlIdPMetadataDocument> samlIdPMetadataCache)
{
+
+ return new WASamlIdPMetadataCacheRefresher(samlIdPMetadataCache);
+ }
+
@Bean
public AuditTrailExecutionPlanConfigurer auditConfigurer(final
WARestClient waRestClient) {
return plan -> plan.registerAuditTrailManager(new
WAAuditTrailManager(waRestClient));
diff --git
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java
index 6642470c98..29ff3cda7f 100644
---
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java
+++
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java
@@ -22,6 +22,7 @@ import java.util.Optional;
import org.apache.syncope.common.lib.to.ClientAppTO;
import org.apache.syncope.common.lib.to.SAML2SPClientAppTO;
import org.apache.syncope.common.lib.wa.WAClientApp;
+import org.apache.syncope.common.rest.api.service.SAML2IdPEntityService;
import org.apereo.cas.configuration.support.TriStateBoolean;
import org.apereo.cas.services.RegisteredService;
import org.apereo.cas.services.RegisteredServiceAccessStrategy;
@@ -59,6 +60,10 @@ public class SAML2SPClientAppTOMapper extends
AbstractClientAppMapper {
service.setServiceId(sp.getEntityId());
+ if (sp.getIdp() != null &&
!SAML2IdPEntityService.DEFAULT_OWNER.equals(sp.getIdp())) {
+ service.setIdpMetadataLocation(sp.getIdp());
+ }
+
service.setMetadataLocation(sp.getMetadataLocation());
service.setMetadataSignatureLocation(sp.getMetadataSignatureLocation());
service.setSignAssertions(TriStateBoolean.fromBoolean(sp.isSignAssertions()));
diff --git
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataCacheRefresher.java
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataCacheRefresher.java
new file mode 100644
index 0000000000..d34134653f
--- /dev/null
+++
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataCacheRefresher.java
@@ -0,0 +1,45 @@
+/*
+ * 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.saml.idp.metadata;
+
+import com.github.benmanes.caffeine.cache.Cache;
+import
org.apereo.cas.support.saml.services.idp.metadata.SamlIdPMetadataDocument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import
org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
+
+public class WASamlIdPMetadataCacheRefresher {
+
+ protected static final Logger LOG =
LoggerFactory.getLogger(WASamlIdPMetadataCacheRefresher.class);
+
+ protected final Cache<String, SamlIdPMetadataDocument> metadataCache;
+
+ public WASamlIdPMetadataCacheRefresher(final Cache<String,
SamlIdPMetadataDocument> metadataCache) {
+ this.metadataCache = metadataCache;
+ }
+
+ @EventListener(RefreshScopeRefreshedEvent.class)
+ @Async
+ public void onRefresh(final RefreshScopeRefreshedEvent event) {
+ LOG.info("Cleaning up SAML IdP cache");
+ metadataCache.invalidateAll();
+ }
+}
diff --git
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataGenerator.java
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataGenerator.java
index a4cd354edf..08261c2816 100644
---
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataGenerator.java
+++
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataGenerator.java
@@ -49,7 +49,8 @@ public class WASamlIdPMetadataGenerator extends
BaseSamlIdPMetadataGenerator {
@Override
public String getAppliesToFor(final Optional<SamlRegisteredService>
registeredService) {
return registeredService.
- map(SamlRegisteredService::getName).
+ map(SamlRegisteredService::getIdpMetadataLocation).
+ flatMap(Optional::ofNullable).
orElse(SAML2IdPEntityService.DEFAULT_OWNER);
}
diff --git
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataLocator.java
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataLocator.java
index 8b1a6a79db..9a682e1065 100644
---
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataLocator.java
+++
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/WASamlIdPMetadataLocator.java
@@ -51,17 +51,26 @@ public class WASamlIdPMetadataLocator extends
AbstractSamlIdPMetadataLocator {
this.waRestClient = waRestClient;
}
+ @Override
+ public String getAppliesToFor(final Optional<SamlRegisteredService>
registeredService) {
+ return registeredService.
+ map(SamlRegisteredService::getIdpMetadataLocation).
+ flatMap(Optional::ofNullable).
+ orElse(SAML2IdPEntityService.DEFAULT_OWNER);
+ }
+
protected SAML2IdPEntityTO fetchFromCore(final
Optional<SamlRegisteredService> registeredService) {
SAML2IdPEntityService idpEntityService =
waRestClient.getService(SAML2IdPEntityService.class);
SAML2IdPEntityTO result = null;
try {
- result = idpEntityService.get(registeredService.
- map(SamlRegisteredService::getName).
- orElse(SAML2IdPEntityService.DEFAULT_OWNER));
+ result = idpEntityService.get(getAppliesToFor(registeredService));
} catch (SyncopeClientException e) {
if (e.getType() == ClientExceptionType.NotFound &&
registeredService.isPresent()) {
- result =
idpEntityService.get(SAML2IdPEntityService.DEFAULT_OWNER);
+ String idp = registeredService.get().getIdpMetadataLocation();
+ if (idp == null ||
SAML2IdPEntityService.DEFAULT_OWNER.equals(idp)) {
+ result =
idpEntityService.get(SAML2IdPEntityService.DEFAULT_OWNER);
+ }
} else {
throw e;
}
@@ -71,14 +80,7 @@ public class WASamlIdPMetadataLocator extends
AbstractSamlIdPMetadataLocator {
}
@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) {
+ protected SamlIdPMetadataDocument fetchInternal(final
Optional<SamlRegisteredService> registeredService) {
try {
LOG.info("Locating SAML2 IdP metadata document");
@@ -114,8 +116,7 @@ public class WASamlIdPMetadataLocator extends
AbstractSamlIdPMetadataLocator {
LOG.warn("Not a valid SAML2 IdP metadata document");
return null;
} catch (Exception e) {
- if (e instanceof final SyncopeClientException
syncopeClientException
- && syncopeClientException.getType() ==
ClientExceptionType.NotFound) {
+ if (e instanceof final SyncopeClientException sce && sce.getType()
== ClientExceptionType.NotFound) {
LOG.info(e.getMessage());
} else {
if (LOG.isDebugEnabled()) {
@@ -128,4 +129,25 @@ public class WASamlIdPMetadataLocator extends
AbstractSamlIdPMetadataLocator {
return null;
}
+
+ @Override
+ public SamlIdPMetadataDocument fetch(final Optional<SamlRegisteredService>
registeredService) {
+ String key = getAppliesToFor(registeredService);
+
+ return getMetadataCache().get(key, __ -> {
+ SamlIdPMetadataDocument metadataDocument =
fetchInternal(registeredService);
+ if (metadataDocument != null && metadataDocument.isValid()) {
+ LOG.trace("Fetched and cached SAML IdP metadata document [{}]
under key [{}]", metadataDocument, key);
+ return metadataDocument;
+ }
+
+ LOG.trace("SAML IdP metadata document [{}] is considered invalid",
metadataDocument);
+ return null;
+ });
+ }
+
+ @Override
+ public boolean shouldGenerateMetadataFor(final
Optional<SamlRegisteredService> registeredService) {
+ return registeredService.isEmpty() || fetchFromCore(registeredService)
== null;
+ }
}
diff --git a/wa/starter/src/main/resources/wa.properties
b/wa/starter/src/main/resources/wa.properties
index da54a7d426..8c75802d34 100644
--- a/wa/starter/src/main/resources/wa.properties
+++ b/wa/starter/src/main/resources/wa.properties
@@ -74,7 +74,7 @@ cas.standalone.configuration-directory=${syncope.conf.dir}
cas.server.name=http://localhost:8080
cas.server.prefix=${cas.server.name}/syncope-wa
-cas.server.scope=syncope.org
+cas.server.scope=syncope.apache.org
cas.logout.follow-service-redirects=true