This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new 0398acc977 Switch to Spring Boot 3.4 / CAS 7.2 / CXF 4.1 (#969)
0398acc977 is described below
commit 0398acc977feb4b0e0b022966513310a8f909769
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Tue Jan 28 17:33:45 2025 +0100
Switch to Spring Boot 3.4 / CAS 7.2 / CXF 4.1 (#969)
---
.../support/SyncopeNeo4jRepositoryFactory.java | 8 +-
.../apache/syncope/core/logic/SAML2SP4UILogic.java | 2 +-
.../org/apache/syncope/fit/AbstractITCase.java | 39 +--
...{OIDCSRAITCase.java => AbstractOIDCITCase.java} | 45 +---
.../apache/syncope/fit/sra/AbstractSRAITCase.java | 2 +-
.../apache/syncope/fit/sra/OAUTH2SRAITCase.java | 2 +-
.../org/apache/syncope/fit/sra/OIDCSRAITCase.java | 275 +--------------------
.../apache/syncope/fit/ui/SAML2SP4UIITCase.java | 4 -
pom.xml | 66 +----
.../sra/security/pac4j/RedirectionActionUtils.java | 59 -----
.../pac4j/ServerWebExchangeHttpActionAdapter.java | 70 ++++++
.../saml2/SAML2RequestServerLogoutHandler.java | 6 +-
.../SAML2WebSsoAuthenticationRequestWebFilter.java | 4 +-
sra/src/main/resources/sra.properties | 2 +-
.../asciidoc/getting-started/introduction.adoc | 2 +-
.../reference-guide/architecture/core.adoc | 2 +-
.../concepts/attributerepositories.adoc | 14 +-
.../concepts/authenticationmodules.adoc | 36 +--
.../concepts/clientapplications.adoc | 6 +-
.../reference-guide/concepts/entitlements.adoc | 2 +-
.../reference-guide/concepts/policies.adoc | 8 +-
.../asciidoc/reference-guide/concepts/reports.adoc | 2 +-
.../asciidoc/reference-guide/concepts/routes.adoc | 4 +-
.../asciidoc/reference-guide/concepts/tasks.adoc | 8 +-
.../reference-guide/concepts/typemanagement.adoc | 2 +-
.../configuration/configurationparameters.adoc | 2 +-
.../reference-guide/configuration/dbms.adoc | 8 +-
.../reference-guide/configuration/deployment.adoc | 8 +-
.../asciidoc/reference-guide/usage/actuator.adoc | 14 +-
src/main/asciidoc/reference-guide/usage/core.adoc | 2 +-
.../reference-guide/usage/customization.adoc | 8 +-
wa/starter/pom.xml | 11 +-
.../syncope/wa/starter/config/WAContext.java | 12 +-
.../saml/idp/WASamlIdPCasEventListener.java | 31 ---
.../thymeleaf/templates/fragments/footer.html | 20 +-
wa/starter/src/main/resources/wa.properties | 27 +-
.../apache/syncope/wa/starter/AbstractTest.java | 27 +-
37 files changed, 260 insertions(+), 580 deletions(-)
diff --git
a/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/repository/support/SyncopeNeo4jRepositoryFactory.java
b/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/repository/support/SyncopeNeo4jRepositoryFactory.java
index bea0c09b89..109c1ed527 100644
---
a/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/repository/support/SyncopeNeo4jRepositoryFactory.java
+++
b/core/persistence-neo4j/src/main/java/org/springframework/data/neo4j/repository/support/SyncopeNeo4jRepositoryFactory.java
@@ -28,7 +28,8 @@ import
org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryComposition;
import
org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.repository.query.QueryLookupStrategy;
-import
org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
+import org.springframework.data.repository.query.ValueExpressionDelegate;
+import org.springframework.lang.Nullable;
public class SyncopeNeo4jRepositoryFactory extends RepositoryFactorySupport {
@@ -63,10 +64,9 @@ public class SyncopeNeo4jRepositoryFactory extends
RepositoryFactorySupport {
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(
- final QueryLookupStrategy.Key key,
- final QueryMethodEvaluationContextProvider
evaluationContextProvider) {
+ final @Nullable QueryLookupStrategy.Key key, final
ValueExpressionDelegate valueExpressionDelegate) {
- return delegate.getQueryLookupStrategy(key, evaluationContextProvider);
+ return delegate.getQueryLookupStrategy(key, valueExpressionDelegate);
}
@Override
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 12d8415d05..ca96a99001 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
@@ -367,7 +367,7 @@ public class SAML2SP4UILogic extends
AbstractSAML2SP4UILogic {
keyValue = nameID.getValue();
}
- loginResp.setNotOnOrAfter(new
Date(authCreds.getConditions().getNotOnOrAfter().toInstant().toEpochMilli()));
+ loginResp.setNotOnOrAfter(new
Date(authCreds.getConditions().getNotOnOrAfter().toEpochMilli()));
loginResp.setSessionIndex(authCreds.getSessionIndex());
diff --git
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 016026baf3..a3038f2ec1 100644
--- a/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -49,7 +49,6 @@ import
org.apache.syncope.common.rest.api.service.SAML2SP4UIIdPService;
import org.apache.syncope.common.rest.api.service.SRARouteService;
import org.apache.syncope.common.rest.api.service.UserService;
import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
-import org.apache.syncope.fit.sra.AbstractSRAITCase;
import org.apereo.cas.oidc.OidcConstants;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
@@ -60,7 +59,7 @@ import org.slf4j.LoggerFactory;
public abstract class AbstractITCase {
- protected static final Logger LOG =
LoggerFactory.getLogger(AbstractSRAITCase.class);
+ protected static final Logger LOG =
LoggerFactory.getLogger(AbstractITCase.class);
protected static final String ADMIN_UNAME = "admin";
@@ -159,45 +158,53 @@ public abstract class AbstractITCase {
protected static Triple<String, String, String> parseSAMLRequestForm(final
String body) {
FormElement form = (FormElement)
Jsoup.parse(body).body().getElementsByTag("form").first();
assertNotNull(form);
+ LOG.debug("SAML Request Form: {}", form.outerHtml());
String action = form.attr("action");
assertNotNull(action);
+ LOG.debug("SAML Request Form action: {}", action);
- Optional<String> relayState = form.formData().stream().
+ String relayState = form.formData().stream().
filter(keyval -> "RelayState".equals(keyval.key())).
map(Connection.KeyVal::value).
- findFirst();
- assertTrue(relayState.isPresent());
+ findFirst().
+ orElseThrow(() -> new IllegalArgumentException("No RelayState
found"));
+ LOG.debug("SAML Request Form RelayState: {}", relayState);
- Optional<String> samlRequest = form.formData().stream().
+ String samlRequest = form.formData().stream().
filter(keyval -> "SAMLRequest".equals(keyval.key())).
map(Connection.KeyVal::value).
- findFirst();
- assertTrue(samlRequest.isPresent());
+ findFirst().
+ orElseThrow(() -> new IllegalArgumentException("No SAMLRequest
found"));
+ LOG.debug("SAML Request Form SAMLRequest: {}", samlRequest);
- return Triple.of(action, relayState.get(), samlRequest.get());
+ return Triple.of(action, relayState, samlRequest);
}
protected static Triple<String, String, String>
parseSAMLResponseForm(final String body) {
FormElement form = (FormElement)
Jsoup.parse(body).body().getElementsByTag("form").first();
assertNotNull(form);
+ LOG.debug("SAML Response Form: {}", form.outerHtml());
String action = form.attr("action");
assertNotNull(action);
+ LOG.debug("SAML Response Form action: {}", action);
- Optional<String> relayState = form.formData().stream().
+ String relayState = form.formData().stream().
filter(keyval -> "RelayState".equals(keyval.key())).
map(Connection.KeyVal::value).
- findFirst();
- assertTrue(relayState.isPresent());
+ findFirst().
+ orElseThrow(() -> new IllegalArgumentException("No RelayState
found"));
+ LOG.debug("SAML Response Form RelayState: {}", relayState);
- Optional<String> samlResponse = form.formData().stream().
+ String samlResponse = form.formData().stream().
filter(keyval -> "SAMLResponse".equals(keyval.key())).
map(Connection.KeyVal::value).
- findFirst();
- assertTrue(samlResponse.isPresent());
+ findFirst().
+ orElseThrow(() -> new IllegalArgumentException("No
SAMLResponse found"));
+ LOG.debug("SAML Response Form SAMLResponse: {}", samlResponse);
- return Triple.of(action, relayState.get(), samlResponse.get());
+ return Triple.of(action, relayState, samlResponse);
}
protected static String extractWAExecution(final String body) {
diff --git
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractOIDCITCase.java
similarity index 89%
copy from
fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
copy to
fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractOIDCITCase.java
index 0ef72a1366..2f5ae3042c 100644
---
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
+++
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractOIDCITCase.java
@@ -27,7 +27,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
-import static org.junit.jupiter.api.Assumptions.assumeTrue;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -38,15 +37,11 @@ import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.IOException;
-import java.io.InputStream;
-import java.lang.invoke.MethodHandles;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.http.Consts;
import org.apache.http.HttpStatus;
@@ -71,10 +66,9 @@ import org.apache.syncope.common.rest.api.RESTHeaders;
import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
import org.apereo.cas.oidc.OidcConstants;
import org.jsoup.Jsoup;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-public class OIDCSRAITCase extends AbstractSRAITCase {
+abstract class AbstractOIDCITCase extends AbstractSRAITCase {
protected static String SRA_REGISTRATION_ID;
@@ -86,13 +80,6 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
protected static String TOKEN_URI;
- @BeforeAll
- public static void startSRA() throws IOException, InterruptedException,
TimeoutException {
-
assumeTrue(OIDCSRAITCase.class.equals(MethodHandles.lookup().lookupClass()));
-
- doStartSRA("oidc");
- }
-
protected static void oidcClientAppSetup(
final String appName,
final String sraRegistrationId,
@@ -159,30 +146,8 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
WA_CONFIG_SERVICE.pushToWA(WAConfigService.PushSubject.clientApps,
List.of());
}
- @BeforeAll
- public static void clientAppSetup() {
-
assumeTrue(OIDCSRAITCase.class.equals(MethodHandles.lookup().lookupClass()));
-
- Properties props = new Properties();
- try (InputStream propStream =
OIDCSRAITCase.class.getResourceAsStream("/sra-oidc.properties")) {
- props.load(propStream);
- } catch (Exception e) {
- fail("Could not load /sra-oidc.properties", e);
- }
- SRA_REGISTRATION_ID = "OIDC";
- CLIENT_APP_ID = 1L;
- CLIENT_ID = props.getProperty("sra.oidc.client-id");
- assertNotNull(CLIENT_ID);
- CLIENT_SECRET = props.getProperty("sra.oidc.client-secret");
- assertNotNull(CLIENT_SECRET);
- TOKEN_URI = WA_ADDRESS + "/oidc/accessToken";
-
- oidcClientAppSetup(
- OIDCSRAITCase.class.getName(), SRA_REGISTRATION_ID,
CLIENT_APP_ID, CLIENT_ID, CLIENT_SECRET);
- }
-
@Test
- public void web() throws IOException {
+ void web() throws IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpClientContext context = HttpClientContext.create();
context.setCookieStore(new BasicCookieStore());
@@ -279,12 +244,10 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
groups.stream().anyMatch(g -> ((Map<String, String>)
g).equals(Map.of("groupName", "citizen")));
}
- protected boolean checkIdToken() {
- return true;
- }
+ protected abstract boolean checkIdToken();
@Test
- public void rest() throws IOException, ParseException {
+ void rest() throws IOException, ParseException {
// 0. access public route
WebClient client = WebClient.create(SRA_ADDRESS + "/public/post").
accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON);
diff --git
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractSRAITCase.java
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractSRAITCase.java
index ce9e7ab5ac..2e979013c9 100644
---
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractSRAITCase.java
+++
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/AbstractSRAITCase.java
@@ -65,7 +65,7 @@ import org.apache.syncope.fit.AbstractITCase;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
-public abstract class AbstractSRAITCase extends AbstractITCase {
+abstract class AbstractSRAITCase extends AbstractITCase {
protected static final JsonMapper MAPPER =
JsonMapper.builder().findAndAddModules().build();
diff --git
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
index 4f6cec2040..1d89ac56d5 100644
---
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
+++
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
@@ -32,7 +32,7 @@ import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.junit.jupiter.api.BeforeAll;
-public class OAUTH2SRAITCase extends OIDCSRAITCase {
+class OAUTH2SRAITCase extends AbstractOIDCITCase {
@BeforeAll
public static void startSRA() throws IOException, InterruptedException,
TimeoutException {
diff --git
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
index 0ef72a1366..16bf410049 100644
---
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
+++
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
@@ -18,73 +18,18 @@
*/
package org.apache.syncope.fit.sra;
-import static org.awaitility.Awaitility.await;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.oneOf;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.nimbusds.jwt.JWTClaimsSet;
-import com.nimbusds.jwt.SignedJWT;
-import jakarta.ws.rs.core.Form;
-import jakarta.ws.rs.core.HttpHeaders;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.lang.invoke.MethodHandles;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
import java.util.Properties;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import org.apache.cxf.jaxrs.client.WebClient;
-import org.apache.http.Consts;
-import org.apache.http.HttpStatus;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.impl.client.BasicCookieStore;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.message.BasicNameValuePair;
-import org.apache.http.util.EntityUtils;
-import org.apache.syncope.common.lib.OIDCScopeConstants;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
-import org.apache.syncope.common.lib.types.ClientAppType;
-import org.apache.syncope.common.lib.types.OIDCGrantType;
-import org.apache.syncope.common.lib.types.OIDCSubjectType;
-import org.apache.syncope.common.rest.api.RESTHeaders;
-import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
-import org.apereo.cas.oidc.OidcConstants;
-import org.jsoup.Jsoup;
import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-public class OIDCSRAITCase extends AbstractSRAITCase {
-
- protected static String SRA_REGISTRATION_ID;
-
- protected static Long CLIENT_APP_ID;
-
- protected static String CLIENT_ID;
-
- protected static String CLIENT_SECRET;
-
- protected static String TOKEN_URI;
+class OIDCSRAITCase extends AbstractOIDCITCase {
@BeforeAll
public static void startSRA() throws IOException, InterruptedException,
TimeoutException {
@@ -93,72 +38,6 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
doStartSRA("oidc");
}
- protected static void oidcClientAppSetup(
- final String appName,
- final String sraRegistrationId,
- final Long clientAppId,
- final String clientId,
- final String clientSecret) {
-
- OIDCRPClientAppTO clientApp =
CLIENT_APP_SERVICE.list(ClientAppType.OIDCRP).stream().
- filter(app -> appName.equals(app.getName())).
- map(OIDCRPClientAppTO.class::cast).
- findFirst().
- orElseGet(() -> {
- OIDCRPClientAppTO app = new OIDCRPClientAppTO();
- app.setName(appName);
- app.setRealm(SyncopeConstants.ROOT_REALM);
- app.setClientAppId(clientAppId);
- app.setClientId(clientId);
- app.setClientSecret(clientSecret);
- app.setBypassApprovalPrompt(false);
-
- Response response =
CLIENT_APP_SERVICE.create(ClientAppType.OIDCRP, app);
- if (response.getStatusInfo().getStatusCode() !=
Response.Status.CREATED.getStatusCode()) {
- fail("Could not create OIDC Client App");
- }
-
- return CLIENT_APP_SERVICE.read(
- ClientAppType.OIDCRP,
response.getHeaderString(RESTHeaders.RESOURCE_KEY));
- });
-
- clientApp.setJwtAccessToken(true);
- clientApp.setClientId(clientId);
- clientApp.setClientSecret(clientSecret);
- clientApp.setSubjectType(OIDCSubjectType.PUBLIC);
- clientApp.getRedirectUris().clear();
- clientApp.getRedirectUris().add(SRA_ADDRESS + "/login/oauth2/code/" +
sraRegistrationId);
- clientApp.setSignIdToken(true);
- clientApp.setLogoutUri(SRA_ADDRESS + "/logout");
- clientApp.setAuthPolicy(getAuthPolicy().getKey());
- clientApp.setAttrReleasePolicy(getAttrReleasePolicy().getKey());
- clientApp.getScopes().add(OIDCScopeConstants.OPEN_ID);
- clientApp.getScopes().add(OIDCScopeConstants.PROFILE);
- clientApp.getScopes().add(OIDCScopeConstants.EMAIL);
- clientApp.getSupportedGrantTypes().add(OIDCGrantType.password);
-
clientApp.getSupportedGrantTypes().add(OIDCGrantType.authorization_code);
-
- CLIENT_APP_SERVICE.update(ClientAppType.OIDCRP, clientApp);
-
- await().atMost(60, TimeUnit.SECONDS).pollInterval(20,
TimeUnit.SECONDS).until(() -> {
- try {
- String metadata = WebClient.create(
- WA_ADDRESS + "/oidc/" +
OidcConstants.WELL_KNOWN_OPENID_CONFIGURATION_URL).
- get().readEntity(String.class);
- if (!metadata.contains("groups")) {
-
WA_CONFIG_SERVICE.pushToWA(WAConfigService.PushSubject.conf, List.of());
- throw new IllegalStateException();
- }
-
- return true;
- } catch (Exception e) {
- // ignore
- }
- return false;
- });
- WA_CONFIG_SERVICE.pushToWA(WAConfigService.PushSubject.clientApps,
List.of());
- }
-
@BeforeAll
public static void clientAppSetup() {
assumeTrue(OIDCSRAITCase.class.equals(MethodHandles.lookup().lookupClass()));
@@ -181,158 +60,8 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
OIDCSRAITCase.class.getName(), SRA_REGISTRATION_ID,
CLIENT_APP_ID, CLIENT_ID, CLIENT_SECRET);
}
- @Test
- public void web() throws IOException {
- CloseableHttpClient httpclient = HttpClients.createDefault();
- HttpClientContext context = HttpClientContext.create();
- context.setCookieStore(new BasicCookieStore());
-
- // 1. public
- HttpGet get = new HttpGet(SRA_ADDRESS + "/public/get?" + QUERY_STRING);
- get.addHeader(HttpHeaders.ACCEPT, MediaType.TEXT_HTML);
- get.addHeader(HttpHeaders.ACCEPT_LANGUAGE, EN_LANGUAGE);
- CloseableHttpResponse response = httpclient.execute(get, context);
-
- ObjectNode headers = checkGetResponse(response,
get.getURI().toASCIIString().replace("/public", ""));
- assertFalse(headers.has(HttpHeaders.COOKIE));
-
- // 2. protected
- get = new HttpGet(SRA_ADDRESS + "/protected/get?" + QUERY_STRING);
- String originalRequestURI = get.getURI().toASCIIString();
- get.addHeader(HttpHeaders.ACCEPT, MediaType.TEXT_HTML);
- get.addHeader(HttpHeaders.ACCEPT_LANGUAGE, EN_LANGUAGE);
- response = httpclient.execute(get, context);
- assertEquals(HttpStatus.SC_OK,
response.getStatusLine().getStatusCode());
-
- // 2a. redirected to WA login screen
- String responseBody = EntityUtils.toString(response.getEntity());
- response = authenticateToWA("bellini", "password", responseBody,
httpclient, context);
-
- // 2b. WA attribute consent screen
- if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
- responseBody = EntityUtils.toString(response.getEntity());
- String execution = extractWAExecution(responseBody);
-
- List<NameValuePair> form = new ArrayList<>();
- form.add(new BasicNameValuePair("_eventId", "confirm"));
- form.add(new BasicNameValuePair("execution", execution));
- form.add(new BasicNameValuePair("option", "1"));
- form.add(new BasicNameValuePair("reminder", "30"));
- form.add(new BasicNameValuePair("reminderTimeUnit", "days"));
-
- HttpPost post = new HttpPost(WA_ADDRESS + "/login");
- post.addHeader(HttpHeaders.ACCEPT, MediaType.TEXT_HTML);
- post.addHeader(HttpHeaders.ACCEPT_LANGUAGE, EN_LANGUAGE);
- post.setEntity(new UrlEncodedFormEntity(form, Consts.UTF_8));
- response = httpclient.execute(post, context);
- }
- assertEquals(HttpStatus.SC_MOVED_TEMPORARILY,
response.getStatusLine().getStatusCode());
-
- // 2c. WA scope consent screen
- get = new
HttpGet(response.getLastHeader(HttpHeaders.LOCATION).getValue());
- get.addHeader(HttpHeaders.ACCEPT, MediaType.TEXT_HTML);
- get.addHeader(HttpHeaders.ACCEPT_LANGUAGE, EN_LANGUAGE);
- response = httpclient.execute(get, context);
- assertEquals(HttpStatus.SC_OK,
response.getStatusLine().getStatusCode());
-
- responseBody = EntityUtils.toString(response.getEntity());
-
- String allow = Jsoup.parse(responseBody).body().
- getElementsByTag("a").select("a[name=allow]").first().
- attr("href");
- assertNotNull(allow);
-
- // 2d. finally get requested content
- get = new HttpGet(allow);
- get.addHeader(HttpHeaders.ACCEPT, MediaType.TEXT_HTML);
- get.addHeader(HttpHeaders.ACCEPT_LANGUAGE, EN_LANGUAGE);
- response = httpclient.execute(get, context);
-
- headers = checkGetResponse(response,
originalRequestURI.replace("/protected", ""));
-
assertTrue(headers.get(HttpHeaders.COOKIE).asText().contains("SESSION"));
-
- // 3. logout
- get = new HttpGet(SRA_ADDRESS + "/protected/logout");
- get.addHeader(HttpHeaders.ACCEPT_LANGUAGE, EN_LANGUAGE);
- response = httpclient.execute(get, context);
- checkLogout(response);
- }
-
- @SuppressWarnings("unchecked")
- private void checkJWT(final String token, final boolean idToken) throws
ParseException {
- assertNotNull(token);
- SignedJWT jwt = SignedJWT.parse(token);
- assertNotNull(jwt);
- JWTClaimsSet idTokenClaimsSet = jwt.getJWTClaimsSet();
- assertEquals("verdi", idTokenClaimsSet.getSubject());
- if (idToken) {
- assertEquals("verdi",
idTokenClaimsSet.getStringClaim("preferred_username"));
- }
- assertEquals("[email protected]",
idTokenClaimsSet.getStringClaim("email"));
- assertEquals("Verdi", idTokenClaimsSet.getStringClaim("family_name"));
- assertEquals("Giuseppe",
idTokenClaimsSet.getStringClaim("given_name"));
- assertEquals("Giuseppe Verdi",
idTokenClaimsSet.getStringClaim("name"));
- List<Object> groups = idTokenClaimsSet.getListClaim("groups");
- assertEquals(3, groups.size());
- groups.stream().anyMatch(g -> ((Map<String, String>)
g).equals(Map.of("groupName", "root")));
- groups.stream().anyMatch(g -> ((Map<String, String>)
g).equals(Map.of("groupName", "child")));
- groups.stream().anyMatch(g -> ((Map<String, String>)
g).equals(Map.of("groupName", "citizen")));
- }
-
+ @Override
protected boolean checkIdToken() {
return true;
}
-
- @Test
- public void rest() throws IOException, ParseException {
- // 0. access public route
- WebClient client = WebClient.create(SRA_ADDRESS + "/public/post").
-
accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON);
- Response response = client.post(null);
- assertEquals(HttpStatus.SC_OK, response.getStatus());
-
- // 1. obtain id and access tokens
- Form form = new Form().
- param("grant_type", "password").
- param("client_id", CLIENT_ID).
- param("client_secret", CLIENT_SECRET).
- param("username", "verdi").
- param("password", "password").
- param("scope", "openid profile email syncope");
- response = WebClient.create(TOKEN_URI).post(form);
- assertEquals(HttpStatus.SC_OK, response.getStatus());
-
assertTrue(response.getHeaderString(HttpHeaders.CONTENT_TYPE).startsWith(MediaType.APPLICATION_JSON));
-
- JsonNode json = MAPPER.readTree(response.readEntity(String.class));
-
- if (checkIdToken()) {
- // 1a. take and verify id_token
- String idToken = json.get("id_token").asText();
- assertNotNull(idToken);
- checkJWT(idToken, true);
- }
-
- // 1b. take and verify access_token
- String accessToken = json.get("access_token").asText();
- checkJWT(accessToken, false);
-
- // 2. access protected route
- client = WebClient.create(SRA_ADDRESS + "/protected/post").
- authorization("Bearer " + accessToken).
-
accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON);
- response = client.post(null);
-
- assertEquals(HttpStatus.SC_OK, response.getStatus());
-
- json = MAPPER.readTree(response.readEntity(String.class));
-
- ObjectNode headers = (ObjectNode) json.get("headers");
- assertEquals(MediaType.APPLICATION_JSON,
headers.get(HttpHeaders.ACCEPT).asText());
- assertEquals(MediaType.APPLICATION_JSON,
headers.get(HttpHeaders.CONTENT_TYPE).asText());
- assertThat(headers.get("X-Forwarded-Host").asText(),
is(oneOf("localhost:8080", "127.0.0.1:8080")));
-
- String withHost =
client.getBaseURI().toASCIIString().replace("/protected", "");
- String withIP = withHost.replace("localhost", "127.0.0.1");
- assertThat(json.get("url").asText(), is(oneOf(withHost, withIP)));
- }
}
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 929824c8c4..9a869059b1 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
@@ -242,10 +242,6 @@ public class SAML2SP4UIITCase extends AbstractUIITCase {
// 2c. WA attribute consent screen
if (isOk) {
- // check attribute repository
- assertTrue(responseBody.contains("identifier"));
- assertTrue(responseBody.contains("[value1]"));
-
String execution = extractWAExecution(responseBody);
List<NameValuePair> form = new ArrayList<>();
diff --git a/pom.xml b/pom.xml
index f34696ee67..c5b6cf8fb8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -392,7 +392,7 @@ under the License.
</contributors>
<properties>
-
<project.build.outputTimestamp>2024-12-27T11:02:14Z</project.build.outputTimestamp>
+
<project.build.outputTimestamp>2025-01-27T11:24:15Z</project.build.outputTimestamp>
<syncope.version>${project.version}</syncope.version>
<connid.version>1.6.0.0-SNAPSHOT</connid.version>
@@ -410,12 +410,12 @@ under the License.
<connid.cmd.version>0.5</connid.cmd.version>
<connid.kafka.version>1.0.0</connid.kafka.version>
- <cxf.version>4.0.6</cxf.version>
+ <cxf.version>4.1.0</cxf.version>
<bouncycastle.version>1.80</bouncycastle.version>
<nimbus-jose-jwt.version>10.0.1</nimbus-jose-jwt.version>
- <spring-boot.version>3.3.8</spring-boot.version>
- <spring-cloud-gateway.version>4.1.6</spring-cloud-gateway.version>
+ <spring-boot.version>3.4.2</spring-boot.version>
+ <spring-cloud-gateway.version>4.2.0</spring-cloud-gateway.version>
<openjpa.version>4.0.1</openjpa.version>
@@ -436,9 +436,9 @@ under the License.
<commons-jexl.version>3.4.0</commons-jexl.version>
<commons-text.version>1.13.0</commons-text.version>
- <pac4j.version>6.0.6</pac4j.version>
+ <pac4j.version>6.1.0</pac4j.version>
- <cas.version>7.1.4</cas.version>
+ <cas.version>7.2.0-RC4</cas.version>
<cas-client.version>4.0.4</cas-client.version>
<swagger-core.version>2.2.28</swagger-core.version>
@@ -498,7 +498,7 @@ under the License.
<cargo.rmi.port>9805</cargo.rmi.port>
<cargo.deployable.ping.timeout>60000</cargo.deployable.ping.timeout>
- <tomcat.version>10.1.33</tomcat.version>
+ <tomcat.version>10.1.34</tomcat.version>
<wildfly.version>35.0.0.Final</wildfly.version>
<payara.version>6.2025.1</payara.version>
<jakarta.faces.version>4.1.2</jakarta.faces.version>
@@ -1360,7 +1360,7 @@ under the License.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-wiremock</artifactId>
- <version>4.1.5</version>
+ <version>${spring-cloud-gateway.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -2052,11 +2052,11 @@ under the License.
<link>https://commons.apache.org/proper/commons-lang/javadocs/api-release/</link>
<link>https://commons.apache.org/proper/commons-jexl/apidocs/</link>
<link>https://tika.apache.org/3.0.0/api/</link>
- <link>https://docs.spring.io/spring-boot/3.3/api/java/</link>
-
<link>https://docs.spring.io/spring-framework/docs/6.1.x/javadoc-api/</link>
-
<link>https://docs.spring.io/spring-security/site/docs/6.3.6/api/</link>
+ <link>https://docs.spring.io/spring-boot/3.4/api/java/</link>
+
<link>https://docs.spring.io/spring-framework/docs/6.2.x/javadoc-api/</link>
+
<link>https://docs.spring.io/spring-security/site/docs/6.4.x/api/</link>
<link>https://www.flowable.com/open-source/docs/javadocs/</link>
- <link>https://docs.swagger.io/swagger-core/v2.2.27/apidocs/</link>
+ <link>https://docs.swagger.io/swagger-core/v2.2.28/apidocs/</link>
</links>
<additionalOptions>
<additionalOption>--legal-notices</additionalOption>
@@ -2345,48 +2345,6 @@ under the License.
</plugins>
</build>
</profile>
-
- <profile>
- <id>jdk24</id>
-
- <activation>
- <jdk>[24,)</jdk>
- </activation>
-
- <properties>
- <mockito.version>5.15.2</mockito.version>
- <byte-buddy.version>1.16.1</byte-buddy.version>
- </properties>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-junit-jupiter</artifactId>
- <version>${mockito.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>${mockito.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>net.bytebuddy</groupId>
- <artifactId>byte-buddy</artifactId>
- <version>${byte-buddy.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>net.bytebuddy</groupId>
- <artifactId>byte-buddy-agent</artifactId>
- <version>${byte-buddy.version}</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- </profile>
</profiles>
<modules>
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
deleted file mode 100644
index 63cbc6a68a..0000000000
---
a/sra/src/main/java/org/apache/syncope/sra/security/pac4j/RedirectionActionUtils.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.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;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import reactor.core.publisher.Mono;
-
-public final class RedirectionActionUtils {
-
- public static Mono<Void> handle(
- final RedirectionAction action,
- final ServerWebExchangeContext swec) {
-
- 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();
- }
-
- 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())));
- });
- }
-
- throw new IllegalArgumentException("Unsupported Action: " +
action.getClass().getName());
- }
-
- private RedirectionActionUtils() {
- // private constructor for static utility class
- }
-}
diff --git
a/sra/src/main/java/org/apache/syncope/sra/security/pac4j/ServerWebExchangeHttpActionAdapter.java
b/sra/src/main/java/org/apache/syncope/sra/security/pac4j/ServerWebExchangeHttpActionAdapter.java
new file mode 100644
index 0000000000..0e03134b57
--- /dev/null
+++
b/sra/src/main/java/org/apache/syncope/sra/security/pac4j/ServerWebExchangeHttpActionAdapter.java
@@ -0,0 +1,70 @@
+/*
+ * 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.sra.security.pac4j;
+
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+import org.pac4j.core.context.WebContext;
+import org.pac4j.core.exception.TechnicalException;
+import org.pac4j.core.exception.http.HttpAction;
+import org.pac4j.core.exception.http.WithContentAction;
+import org.pac4j.core.exception.http.WithLocationAction;
+import org.pac4j.core.http.adapter.HttpActionAdapter;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import reactor.core.publisher.Mono;
+
+public class ServerWebExchangeHttpActionAdapter implements HttpActionAdapter {
+
+ public static final ServerWebExchangeHttpActionAdapter INSTANCE = new
ServerWebExchangeHttpActionAdapter();
+
+ @Override
+ public Mono<Void> adapt(final HttpAction action, final WebContext context)
{
+ if (action == null) {
+ throw new TechnicalException("No action provided");
+ }
+
+ ServerHttpResponse response = ((ServerWebExchangeContext)
context).getNative().getResponse();
+
+ switch (action) {
+ case WithLocationAction withLocationAction -> {
+ response.setStatusCode(HttpStatus.FOUND);
+
response.getHeaders().setLocation(URI.create(withLocationAction.getLocation()));
+ return response.setComplete();
+ }
+
+ case WithContentAction withContentAction -> {
+ String content =
Optional.ofNullable(withContentAction.getContent()).
+ orElseThrow(() -> new TechnicalException("No content
set for POST AuthnRequest"));
+
+ return Mono.defer(() -> {
+ response.getHeaders().setContentType(MediaType.TEXT_HTML);
+ return response.writeWith(Mono.just(
+
response.bufferFactory().wrap(content.getBytes(StandardCharsets.UTF_8))));
+ });
+ }
+
+ default -> {
+ throw new TechnicalException("Unsupported Action: " +
action.getClass().getName());
+ }
+ }
+ }
+}
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 57f5fcee80..2ada82e1a9 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
@@ -20,8 +20,8 @@ package org.apache.syncope.sra.security.saml2;
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.apache.syncope.sra.security.pac4j.ServerWebExchangeHttpActionAdapter;
import org.pac4j.core.context.CallContext;
import org.pac4j.saml.client.SAML2Client;
import org.pac4j.saml.credentials.SAML2AuthenticationCredentials;
@@ -50,7 +50,7 @@ public class SAML2RequestServerLogoutHandler implements
ServerLogoutHandler {
public Mono<Void> logout(final WebFilterExchange exchange, final
Authentication authentication) {
return exchange.getExchange().getSession().
flatMap(session -> {
- SAML2AuthenticationCredentials credentials =
+ SAML2AuthenticationCredentials credentials =
(SAML2AuthenticationCredentials)
authentication.getPrincipal();
LOG.debug("Creating SAML2 SP Logout Request for IDP[{}]
and Profile[{}]",
@@ -61,7 +61,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),
credentials.getUserProfile(), null).
- map(action ->
RedirectionActionUtils.handle(action, swec)).
+ map(action ->
ServerWebExchangeHttpActionAdapter.INSTANCE.adapt(action, swec)).
orElseThrow(() -> new IllegalStateException("No
action generated")));
}).onErrorResume(Mono::error);
}
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 30c5159723..3fd3e7c50b 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
@@ -20,8 +20,8 @@ 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.security.pac4j.ServerWebExchangeHttpActionAdapter;
import org.apache.syncope.sra.session.SessionUtils;
import org.pac4j.core.context.CallContext;
import org.pac4j.saml.client.SAML2Client;
@@ -67,7 +67,7 @@ public class SAML2WebSsoAuthenticationRequestWebFilter
implements WebFilter {
return saml2Client.getRedirectionAction(
new CallContext(swec, NoOpSessionStore.INSTANCE)).
- map(action ->
RedirectionActionUtils.handle(action, swec)).
+ map(action ->
ServerWebExchangeHttpActionAdapter.INSTANCE.adapt(action, swec)).
orElseThrow(() -> new IllegalStateException("No
action generated"));
}).onErrorResume(Mono::error);
}
diff --git a/sra/src/main/resources/sra.properties
b/sra/src/main/resources/sra.properties
index eb3ae97a2a..a4973bb1c3 100644
--- a/sra/src/main/resources/sra.properties
+++ b/sra/src/main/resources/sra.properties
@@ -20,7 +20,7 @@ spring.main.banner-mode=log
server.port=8080
-management.endpoint.gateway.enabled=true
+management.endpoint.gateway.access=UNRESTRICTED
management.endpoints.web.exposure.include=info,health,loggers,metrics,gateway,sraSessions
management.endpoint.health.show-details=ALWAYS
management.endpoint.env.show-values=WHEN_AUTHORIZED
diff --git a/src/main/asciidoc/getting-started/introduction.adoc
b/src/main/asciidoc/getting-started/introduction.adoc
index 2317c9c329..e74249d295 100644
--- a/src/main/asciidoc/getting-started/introduction.adoc
+++ b/src/main/asciidoc/getting-started/introduction.adoc
@@ -146,7 +146,7 @@ http://www.bpmn.org/[BPMN 2.0^] implementations - or define
new, custom ones.
* *_Persistence_* manages all data (users, groups, attributes, resources,
...) at a high level
using a standard https://en.wikipedia.org/wiki/Jakarta_Persistence[Jakarta
Persistence 3.1] approach. The data is persisted to an underlying
database, referred to as *_Internal Storage_*. Consistency is ensured via the
comprehensive
-https://docs.spring.io/spring-framework/reference/6.1/data-access/transaction.html[transaction
management^]
+https://docs.spring.io/spring-framework/reference/6.2/data-access/transaction.html[transaction
management^]
provided by the Spring Framework. +
Globally, this offers the ability to easily scale up to a million entities and
at the same time allows great portability with no code
changes: PostgreSQL, MySQL, MariaDB and Oracle are fully supported deployment
options.
diff --git a/src/main/asciidoc/reference-guide/architecture/core.adoc
b/src/main/asciidoc/reference-guide/architecture/core.adoc
index 3d04e5bb05..712c6fee1d 100644
--- a/src/main/asciidoc/reference-guide/architecture/core.adoc
+++ b/src/main/asciidoc/reference-guide/architecture/core.adoc
@@ -83,7 +83,7 @@ All data (users, groups, attributes, resources, ...) is
internally managed at a
https://en.wikipedia.org/wiki/Jakarta_Persistence[Jakarta Persistence 3.1]
approach based on https://openjpa.apache.org[Apache OpenJPA^].
The data is persisted into an underlying
database, referred to as *_Internal Storage_*. Consistency is ensured via the
comprehensive
-https://docs.spring.io/spring-framework/reference/6.1/data-access/transaction.html[transaction
management^]
+https://docs.spring.io/spring-framework/reference/6.2/data-access/transaction.html[transaction
management^]
provided by the Spring Framework.
Globally, this offers the ability to easily scale up to a million entities and
at the same time allows great portability
diff --git
a/src/main/asciidoc/reference-guide/concepts/attributerepositories.adoc
b/src/main/asciidoc/reference-guide/concepts/attributerepositories.adoc
index 0aad019ae1..02021734d3 100644
--- a/src/main/asciidoc/reference-guide/concepts/attributerepositories.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/attributerepositories.adoc
@@ -23,12 +23,12 @@ certain <<policies-attribute-release,Attribute Release
Policy>>.
Some attribute repositories are provided:
-*
https://apereo.github.io/cas/7.1.x/integration/Attribute-Resolution-JDBC.html[Database^]
-*
https://apereo.github.io/cas/7.1.x/integration/Attribute-Resolution-LDAP.html[LDAP^]
-*
https://apereo.github.io/cas/7.1.x/integration/Attribute-Resolution-Stub.html[Stub^]
-*
https://apereo.github.io/cas/7.1.x/integration/Attribute-Resolution-Syncope.html[Syncope^]
-*
https://apereo.github.io/cas/7.1.x/integration/Attribute-Resolution-AzureAD.html[Azure
Active Directory^]
-*
https://apereo.github.io/cas/7.1.x/integration/Attribute-Resolution-Okta.html[Okta^]
+*
https://apereo.github.io/cas/development/integration/Attribute-Resolution-JDBC.html[Database^]
+*
https://apereo.github.io/cas/development/integration/Attribute-Resolution-LDAP.html[LDAP^]
+*
https://apereo.github.io/cas/development/integration/Attribute-Resolution-Stub.html[Stub^]
+*
https://apereo.github.io/cas/development/integration/Attribute-Resolution-Syncope.html[Syncope^]
+*
https://apereo.github.io/cas/development/integration/Attribute-Resolution-AzureAD.html[Azure
Active Directory^]
+*
https://apereo.github.io/cas/development/integration/Attribute-Resolution-Okta.html[Okta^]
[TIP]
====
@@ -51,4 +51,4 @@ class.
[NOTE]
Attribute Repositories are dynamically translated into
-https://apereo.github.io/cas/7.1.x/integration/Attribute-Resolution.html[CAS
Attribute Resolution^] configuration.
+https://apereo.github.io/cas/development/integration/Attribute-Resolution.html[CAS
Attribute Resolution^] configuration.
diff --git
a/src/main/asciidoc/reference-guide/concepts/authenticationmodules.adoc
b/src/main/asciidoc/reference-guide/concepts/authenticationmodules.adoc
index 1930eb16f6..89c691e217 100644
--- a/src/main/asciidoc/reference-guide/concepts/authenticationmodules.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/authenticationmodules.adoc
@@ -24,24 +24,24 @@ technology or repository, in the context of a certain
<<policies-authentication,
Several authentication modules are provided:
* Principal Authentication:
- **
https://apereo.github.io/cas/7.1.x/authentication/Database-Authentication.html[Database^]
- **
https://apereo.github.io/cas/7.1.x/authentication/JAAS-Authentication.html[JAAS^]
- **
https://apereo.github.io/cas/7.1.x/authentication/LDAP-Authentication.html[LDAP^]
- **
https://apereo.github.io/cas/7.1.x/authentication/SPNEGO-Authentication.html[SPNEGO^]
- **
https://apereo.github.io/cas/7.1.x/authentication/Syncope-Authentication.html[Syncope^]
- **
https://apereo.github.io/cas/7.1.x/authentication/Azure-ActiveDirectory-Authentication.html[Azure
Active Directory^]
- **
https://apereo.github.io/cas/7.1.x/authentication/Okta-Authentication.html[Okta^]
- **
https://apereo.github.io/cas/7.1.x/authentication/X509-Authentication.html[X509^]
- **
https://apereo.github.io/cas/7.1.x/integration/Delegate-Authentication-Generic-OpenID-Connect.html[OpenID
Connect^]
- **
https://apereo.github.io/cas/7.1.x/integration/Delegate-Authentication-OAuth20.html[OAuth2^]
- **
https://apereo.github.io/cas/7.1.x/integration/Delegate-Authentication-SAML.htmll[SAML^]
- **
https://apereo.github.io/cas/7.1.x/integration/Delegate-Authentication-Apple.html[Apple
Signin^]
- **
https://apereo.github.io/cas/7.1.x/integration/Delegate-Authentication-Azure-AD.html[Azure
Active Directory (OIDC)^]
- **
https://apereo.github.io/cas/7.1.x/integration/Delegate-Authentication-Google-OpenID-Connect.html[Google
OpenID^]
- **
https://apereo.github.io/cas/7.1.x/integration/Delegate-Authentication-Keycloak.html[Keycloak^]
+ **
https://apereo.github.io/cas/development/authentication/Database-Authentication.html[Database^]
+ **
https://apereo.github.io/cas/development/authentication/JAAS-Authentication.html[JAAS^]
+ **
https://apereo.github.io/cas/development/authentication/LDAP-Authentication.html[LDAP^]
+ **
https://apereo.github.io/cas/development/authentication/SPNEGO-Authentication.html[SPNEGO^]
+ **
https://apereo.github.io/cas/development/authentication/Syncope-Authentication.html[Syncope^]
+ **
https://apereo.github.io/cas/development/authentication/Azure-ActiveDirectory-Authentication.html[Azure
Active Directory^]
+ **
https://apereo.github.io/cas/development/authentication/Okta-Authentication.html[Okta^]
+ **
https://apereo.github.io/cas/development/authentication/X509-Authentication.html[X509^]
+ **
https://apereo.github.io/cas/development/integration/Delegate-Authentication-Generic-OpenID-Connect.html[OpenID
Connect^]
+ **
https://apereo.github.io/cas/development/integration/Delegate-Authentication-OAuth20.html[OAuth2^]
+ **
https://apereo.github.io/cas/development/integration/Delegate-Authentication-SAML.htmll[SAML^]
+ **
https://apereo.github.io/cas/development/integration/Delegate-Authentication-Apple.html[Apple
Signin^]
+ **
https://apereo.github.io/cas/development/integration/Delegate-Authentication-Azure-AD.html[Azure
Active Directory (OIDC)^]
+ **
https://apereo.github.io/cas/development/integration/Delegate-Authentication-Google-OpenID-Connect.html[Google
OpenID^]
+ **
https://apereo.github.io/cas/development/integration/Delegate-Authentication-Keycloak.html[Keycloak^]
* MFA:
- **
https://apereo.github.io/cas/7.1.x/mfa/DuoSecurity-Authentication.html[Duo
Security^]
- **
https://apereo.github.io/cas/7.1.x/mfa/GoogleAuthenticator-Authentication.html[Google
Authenticator^]
+ **
https://apereo.github.io/cas/development/mfa/DuoSecurity-Authentication.html[Duo
Security^]
+ **
https://apereo.github.io/cas/development/mfa/GoogleAuthenticator-Authentication.html[Google
Authenticator^]
[TIP]
====
@@ -64,4 +64,4 @@ class.
[NOTE]
Authentication Modules are dynamically translated into
-https://apereo.github.io/cas/7.1.x/authentication/Configuring-Authentication-Components.html#authentication-handlers[CAS
Authentication Handlers^].
+https://apereo.github.io/cas/development/authentication/Configuring-Authentication-Components.html#authentication-handlers[CAS
Authentication Handlers^].
diff --git a/src/main/asciidoc/reference-guide/concepts/clientapplications.adoc
b/src/main/asciidoc/reference-guide/concepts/clientapplications.adoc
index 744b1a81f2..8c12ae2a86 100644
--- a/src/main/asciidoc/reference-guide/concepts/clientapplications.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/clientapplications.adoc
@@ -34,17 +34,17 @@ When defining a client application, the following
parameters shall be specified:
. name - regular expression to match requests
. description - optional textual description
. username attribute provider, mapping to
-https://apereo.github.io/cas/7.1.x/integration/Attribute-Release-PrincipalId-Attribute.html[CAS
Attribute-based Principal Id^]
+https://apereo.github.io/cas/development/integration/Attribute-Release-PrincipalId-Attribute.html[CAS
Attribute-based Principal Id^]
. <<policies-authentication,authentication policy>>
. <<policies-access,access policy>>
. <<policies-attribute-release,attribute release policy>>
. <<policies-ticket-expiration,ticket expiration policy>>
. additional properties
. logout type, mapping to
-https://apereo.github.io/cas/7.1.x/installation/Logout-Single-Signout.html#slo-requests[the
equivalent CAS setting^]
+https://apereo.github.io/cas/development/installation/Logout-Single-Signout.html#slo-requests[the
equivalent CAS setting^]
More parameters are required to be specified depending on the actual client
application type.
[NOTE]
Client Applications are dynamically translated into
-https://apereo.github.io/cas/7.1.x/services/Service-Management.html[CAS
Services^].
+https://apereo.github.io/cas/development/services/Service-Management.html[CAS
Services^].
diff --git a/src/main/asciidoc/reference-guide/concepts/entitlements.adoc
b/src/main/asciidoc/reference-guide/concepts/entitlements.adoc
index 8ac00aa43c..c52e00dee2 100644
--- a/src/main/asciidoc/reference-guide/concepts/entitlements.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/entitlements.adoc
@@ -30,7 +30,7 @@ ifeval::["{snapshotOrRelease}" == "snapshot"]
https://github.com/apache/syncope/blob/master/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/RealmLogic.java[RealmLogic^]
endif::[]
, the
-https://docs.spring.io/spring-security/reference/6.3/servlet/authorization/method-security.html#authorization-expressions[`hasRole`
expression^]
+https://docs.spring.io/spring-security/reference/6.4/servlet/authorization/method-security.html#authorization-expressions[`hasRole`
expression^]
is used together with one of the standard entitlements to restrict access only
to Users owning the `REALM_SEARCH`
entitlement.
diff --git a/src/main/asciidoc/reference-guide/concepts/policies.adoc
b/src/main/asciidoc/reference-guide/concepts/policies.adoc
index 488015930a..576f5ef7ec 100644
--- a/src/main/asciidoc/reference-guide/concepts/policies.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/policies.adoc
@@ -320,7 +320,7 @@ endif::[]
[NOTE]
Access Policy instances are dynamically translated into
-https://apereo.github.io/cas/7.1.x/services/Configuring-Service-Access-Strategy.html#configure-service-access-strategy[CAS
Service Access Strategy^].
+https://apereo.github.io/cas/development/services/Configuring-Service-Access-Strategy.html#configure-service-access-strategy[CAS
Service Access Strategy^].
[[policies-attribute-release]]
==== Attribute Release
@@ -332,7 +332,7 @@ values.
[NOTE]
Attribute Release Policy instances are dynamically translated into
-https://apereo.github.io/cas/7.1.x/integration/Attribute-Release-Policies.html#attribute-release-policies[CAS
Attribute Release Policy^].
+https://apereo.github.io/cas/development/integration/Attribute-Release-Policies.html#attribute-release-policies[CAS
Attribute Release Policy^].
[[policies-authentication]]
==== Authentication
@@ -359,7 +359,7 @@ be considered successful.
[NOTE]
Authentication Policy instances are dynamically translated into
-https://apereo.github.io/cas/7.1.x/authentication/Configuring-Authentication-Policy.html#authentication-policy[CAS
Authentication Policy^].
+https://apereo.github.io/cas/development/authentication/Configuring-Authentication-Policy.html#authentication-policy[CAS
Authentication Policy^].
[[policies-propagation]]
==== Propagation
@@ -478,4 +478,4 @@ Ticket Expiration policies control the duration of various
types of WA sessions.
[NOTE]
Ticket Expiration Policy instances are dynamically translated into
-https://apereo.github.io/cas/7.1.x/ticketing/Configuring-Ticket-Expiration-Policy.html[their
CAS equivalent^].
+https://apereo.github.io/cas/development/ticketing/Configuring-Ticket-Expiration-Policy.html[their
CAS equivalent^].
diff --git a/src/main/asciidoc/reference-guide/concepts/reports.adoc
b/src/main/asciidoc/reference-guide/concepts/reports.adoc
index 726c45b22a..428933142b 100644
--- a/src/main/asciidoc/reference-guide/concepts/reports.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/reports.adoc
@@ -34,4 +34,4 @@ endif::[]
providing the custom logic to extract information from Syncope and generate
output according to the configured mime type
* scheduling information:
** when to start
-**
https://docs.spring.io/spring-framework/reference/6.1/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
+**
https://docs.spring.io/spring-framework/reference/6.2/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
diff --git a/src/main/asciidoc/reference-guide/concepts/routes.adoc
b/src/main/asciidoc/reference-guide/concepts/routes.adoc
index ff62175562..761e5b100c 100644
--- a/src/main/asciidoc/reference-guide/concepts/routes.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/routes.adoc
@@ -50,7 +50,7 @@ The received response, after being post-processed by matching
route's _filters_,
==== Predicates
Inside Route definition, each predicate will be referring to some Spring Cloud
Gateway's
-https://docs.spring.io/spring-cloud-gateway/docs/4.1.x/reference/html/#gateway-request-predicates-factories[Predicate
factory^]:
+https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway/request-predicates-factories.html[Predicate
factory^]:
* `AFTER` matches requests that happen after the specified datetime;
* `BEFORE` matches requests that happen before the specified datetime;
@@ -74,7 +74,7 @@ endif::[]
==== Filters
Inside Route definition, each filter will be referring to some Spring Cloud
Gateway's
-https://docs.spring.io/spring-cloud-gateway/docs/4.1.x/reference/html/#gatewayfilter-factories[Filter
factory^]:
+https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway/gatewayfilter-factories.html[Filter
factory^]:
* `ADD_REQUEST_HEADER` adds a header to the downstream request's headers;
* `ADD_REQUEST_PARAMETER` adds a parameter too the downstream request's
query string;
diff --git a/src/main/asciidoc/reference-guide/concepts/tasks.adoc
b/src/main/asciidoc/reference-guide/concepts/tasks.adoc
index bab4b1c087..fe9c3fc9f5 100644
--- a/src/main/asciidoc/reference-guide/concepts/tasks.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/tasks.adoc
@@ -101,7 +101,7 @@ When defining a pull task, the following information must
be provided:
* <<pull-templates,entity templates>>
* scheduling information:
** when to start
-**
https://docs.spring.io/spring-framework/reference/6.1/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
+**
https://docs.spring.io/spring-framework/reference/6.2/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
[NOTE]
====
@@ -189,7 +189,7 @@ When defining a push task, the following information must
be provided:
* optional <<pushactions,push action(s)>>
* scheduling information:
** when to start
-**
https://docs.spring.io/spring-framework/reference/6.1/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
+**
https://docs.spring.io/spring-framework/reference/6.2/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
[NOTE]
====
@@ -258,7 +258,7 @@ When defining a macro task, the following information must
be provided:
list, update or execute the given macro task
* scheduling information:
** when to start
-**
https://docs.spring.io/spring-framework/reference/6.1/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
+**
https://docs.spring.io/spring-framework/reference/6.2/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
===== MacroActions
@@ -289,7 +289,7 @@ endif::[]
providing the custom logic to execute
* scheduling information:
** when to start
-**
https://docs.spring.io/spring-framework/reference/6.1/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
+**
https://docs.spring.io/spring-framework/reference/6.2/integration/scheduling.html#scheduling-cron-expression[cron
expression^]
[TIP]
====
diff --git a/src/main/asciidoc/reference-guide/concepts/typemanagement.adoc
b/src/main/asciidoc/reference-guide/concepts/typemanagement.adoc
index daf6de4689..a0699b8bcf 100644
--- a/src/main/asciidoc/reference-guide/concepts/typemanagement.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/typemanagement.adoc
@@ -48,7 +48,7 @@
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/text/DateForma
** `Dropdown` - allows to specify an <<implementations,implementation>> which
will dynamically return the value(s) that
can be selected
** `Encrypted`
-*** secret key (stored or referenced as
https://docs.spring.io/spring-framework/reference/6.1/core/beans/environment.html#beans-using-propertysource[Spring
property^])
+*** secret key (stored or referenced as
https://docs.spring.io/spring-framework/reference/6.2/core/beans/environment.html#beans-using-propertysource[Spring
property^])
*** cipher algorithm
*** whether transparent encryption is to be enabled, e.g. attribute values are
stored as encrypted but available as
cleartext on-demand (requires AES ciphering)
diff --git
a/src/main/asciidoc/reference-guide/configuration/configurationparameters.adoc
b/src/main/asciidoc/reference-guide/configuration/configurationparameters.adoc
index cc8bab7ec9..bba639466b 100644
---
a/src/main/asciidoc/reference-guide/configuration/configurationparameters.adoc
+++
b/src/main/asciidoc/reference-guide/configuration/configurationparameters.adoc
@@ -34,7 +34,7 @@ at runtime, expecially with high-availability.
* `jwt.lifetime.minutes` - validity of
https://en.wikipedia.org/wiki/JSON_Web_Token[JSON Web Token^] values used for
<<rest-authentication-and-authorization,authentication>> (in minutes);
* `notificationjob.cronExpression` -
-https://docs.spring.io/spring-framework/reference/6.1/integration/scheduling.html#scheduling-cron-expression[cron^]
expression describing how
+https://docs.spring.io/spring-framework/reference/6.2/integration/scheduling.html#scheduling-cron-expression[cron^]
expression describing how
frequently the pending <<tasks-notification,notification tasks>> are
processed: empty means disabled;
[NOTE]
Restarting the deployment is required when changing value for this parameter.
diff --git a/src/main/asciidoc/reference-guide/configuration/dbms.adoc
b/src/main/asciidoc/reference-guide/configuration/dbms.adoc
index 9a7cfb5bd5..bf3dd003e4 100644
--- a/src/main/asciidoc/reference-guide/configuration/dbms.adoc
+++ b/src/main/asciidoc/reference-guide/configuration/dbms.adoc
@@ -40,7 +40,7 @@ persistence.domain[0].poolMinIdle=5
as `core/src/main/resources/core-postgresql.properties`.
Do not forget to include `postgresql` as
-https://docs.spring.io/spring-boot/3.3/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
+https://docs.spring.io/spring-boot/3.4/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
for the Core application.
[WARNING]
@@ -73,7 +73,7 @@ persistence.domain[0].poolMinIdle=5
as `core/src/main/resources/core-mysql.properties`.
Do not forget to include `mysql` as
-https://docs.spring.io/spring-boot/3.3/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
+https://docs.spring.io/spring-boot/3.4/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
for the Core application.
[CAUTION]
@@ -110,7 +110,7 @@ persistence.domain[0].poolMinIdle=5
as `core/src/main/resources/core-mariadb.properties`.
Do not forget to include `mariadb` as
-https://docs.spring.io/spring-boot/3.3/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
+https://docs.spring.io/spring-boot/3.4/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
for the Core application.
[CAUTION]
@@ -159,7 +159,7 @@ persistence.domain[0].poolMinIdle=5
as `core/src/main/resources/core-oracle.properties`.
Do not forget to include `oracle` as
-https://docs.spring.io/spring-boot/3.3/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
+https://docs.spring.io/spring-boot/3.4/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
for the Core application.
[WARNING]
diff --git a/src/main/asciidoc/reference-guide/configuration/deployment.adoc
b/src/main/asciidoc/reference-guide/configuration/deployment.adoc
index 48276c09db..2d85e88497 100644
--- a/src/main/asciidoc/reference-guide/configuration/deployment.adoc
+++ b/src/main/asciidoc/reference-guide/configuration/deployment.adoc
@@ -24,7 +24,7 @@ Jakarta EE containers.
[WARNING]
The only exception is <<secure-remote-access>> that, being based on Spring
Cloud Gateway - which in turn is built on
-https://docs.spring.io/spring-framework/reference/6.1/web-reactive.html[Spring
WebFlux^] and
+https://docs.spring.io/spring-framework/reference/6.2/web-reactive.html[Spring
WebFlux^] and
https://projectreactor.io/docs[Project Reactor^], is only available as
standalone application.
[CAUTION]
@@ -51,7 +51,7 @@ applications as standalone fat JAR or WAR files.
[TIP]
Spring Boot applications can also be
-https://docs.spring.io/spring-boot/3.3/how-to/deployment/installing.html[installed
as system services^].
+https://docs.spring.io/spring-boot/3.4/how-to/deployment/installing.html[installed
as system services^].
.Run Core application as standalone under GNU / Linux
====
@@ -71,7 +71,7 @@ $ java -Dsyncope.conf.dir=/opt/syncope/conf \
-jar /opt/syncope/lib/syncope.war
----
Further options can be passed to last command, according to Spring Boot
-https://docs.spring.io/spring-boot/3.3/appendix/application-properties/index.html[documentation^];
+https://docs.spring.io/spring-boot/3.4/appendix/application-properties/index.html[documentation^];
for example:
* `--spring.config.additional-location=/path` +
@@ -283,7 +283,7 @@
javadocPaths=/WEB-INF/lib/syncope-common-idrepo-rest-api-${syncope.version}-java
as `core/src/main/resources/core-wildfy.properties`.
Do not forget to include `widlfly` as
-https://docs.spring.io/spring-boot/3.3/reference/features/profiles.html[Spring
Boot profile^]
+https://docs.spring.io/spring-boot/3.4/reference/features/profiles.html[Spring
Boot profile^]
for the Core application.
[WARNING]
diff --git a/src/main/asciidoc/reference-guide/usage/actuator.adoc
b/src/main/asciidoc/reference-guide/usage/actuator.adoc
index 672f845903..566113fad7 100644
--- a/src/main/asciidoc/reference-guide/usage/actuator.adoc
+++ b/src/main/asciidoc/reference-guide/usage/actuator.adoc
@@ -23,7 +23,7 @@ Spring Boot's actuator endpoints let you monitor and interact
with Syncope compo
Each individual endpoint can be enabled / disabled and exposed over HTTP
(pre-defined, under the `/actuator` subcontext)
or JMX.
-Besides a number of
https://docs.spring.io/spring-boot/3.3/reference/actuator/endpoints.html[built-in
endpoints^],
+Besides a number of
https://docs.spring.io/spring-boot/3.4/reference/actuator/endpoints.html[built-in
endpoints^],
more are made available for each component, as reported below.
[NOTE]
@@ -55,15 +55,15 @@ a| Allows to work with
https://openjpa.apache.org/builds/4.0.1/apache-openjpa/do
|===
| `ssoSessions`
-|
https://apereo.github.io/cas/7.1.x/authentication/Configuring-SSO.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/development/authentication/Configuring-SSO.html#actuator-endpoints[More
details^]
| `registeredServices`
-|
https://apereo.github.io/cas/7.1.x/services/Service-Management.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/development/services/Service-Management.html#actuator-endpoints[More
details^]
| `authenticationHandlers`
-|
https://apereo.github.io/cas/7.1.x/authentication/Configuring-Authentication-Components.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/development/authentication/Configuring-Authentication-Components.html#actuator-endpoints[More
details^]
| `authenticationPolicies`
-|
https://apereo.github.io/cas/7.1.x/authentication/Configuring-Authentication-Policy.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/development/authentication/Configuring-Authentication-Policy.html#actuator-endpoints[More
details^]
| `resolveAttributes`
-|
https://apereo.github.io/cas/7.1.x/integration/Attribute-Resolution.html#actuator-endpoints[More
details^]
+|
https://apereo.github.io/cas/development/integration/Attribute-Resolution.html#actuator-endpoints[More
details^]
|===
@@ -80,6 +80,6 @@ a|
* `DELETE {id}` - removes the session with given `id`
| `gateway`
-|
https://docs.spring.io/spring-cloud-gateway/docs/4.1.x/reference/html/#actuator-api[More
details^]
+|
https://docs.spring.io/spring-cloud-gateway/reference/spring-cloud-gateway/actuator-api.html[More
details^]
|===
diff --git a/src/main/asciidoc/reference-guide/usage/core.adoc
b/src/main/asciidoc/reference-guide/usage/core.adoc
index c15a8af491..c89aab24fe 100644
--- a/src/main/asciidoc/reference-guide/usage/core.adoc
+++ b/src/main/asciidoc/reference-guide/usage/core.adoc
@@ -98,7 +98,7 @@ The set of RESTful services provided by Apache Syncope can be
divided as:
. endpoints disclosing information about the given Syncope deployment
(available <<schema,schema>>, configured
<<extensions,extensions>>, Groups, ...), requiring some sort of shared
authentication defined by the
`anonymousKey` value in the `security.properties` file - for more
information, read about Spring Security's
-https://docs.spring.io/spring-security/reference/6.3/servlet/authentication/anonymous.html#page-title[Anonymous
Authentication^];
+https://docs.spring.io/spring-security/reference/6.4/servlet/authentication/anonymous.html#page-title[Anonymous
Authentication^];
. endpoints for self-service (self-update, password change, ...), requiring
user authentication and no entitlements;
. endpoints for administrative operations, requiring user authentication with
authorization granted by the related
<<entitlements,entitlements>>, handed over to users via <<roles,roles>>.
diff --git a/src/main/asciidoc/reference-guide/usage/customization.adoc
b/src/main/asciidoc/reference-guide/usage/customization.adoc
index 4a11d2e3b9..611f5a7c77 100644
--- a/src/main/asciidoc/reference-guide/usage/customization.adoc
+++ b/src/main/asciidoc/reference-guide/usage/customization.adoc
@@ -155,7 +155,7 @@ endif::[]
===== Extending configuration
Apache Syncope <<architecture,components>> are built on
https://spring.io/projects/spring-boot[Spring Boot^],
hence designing and extending Syncope configuration very much comes down to
-https://docs.spring.io/spring-boot/3.3/index.html[their guide^], some aspects
of which are briefly
+https://docs.spring.io/spring-boot/3.4/index.html[their guide^], some aspects
of which are briefly
highlighted here.
To design your own configuration class, take inspiration from the following
sample:
@@ -236,7 +236,7 @@ $ mkdir /opt/syncope/conf
[TIP]
====
The `conf` directory must be configured for deployment, following Spring Boot's
-https://docs.spring.io/spring-boot/3.3/reference/features/external-config.html[Externalized
Configuration^]
+https://docs.spring.io/spring-boot/3.4/reference/features/external-config.html[Externalized
Configuration^]
settings; with above reference:
* <<standalone>>: `--spring.config.additional-location=/opt/syncope/conf/`
@@ -383,7 +383,7 @@ elasticsearch.numberOfReplicas=1
as `core/src/main/resources/core-elasticsearch.properties`.
Do not forget to include `elasticsearch` as
-https://docs.spring.io/spring-boot/3.3/reference/features/profiles.html[Spring
Boot profile^]
+https://docs.spring.io/spring-boot/3.4/reference/features/profiles.html[Spring
Boot profile^]
for the Core application.
If needed, customize the `@Bean` declarations from
@@ -436,7 +436,7 @@ opensearch.numberOfReplicas=1
as `core/src/main/resources/core-opensearch.properties`.
Do not forget to include `opensearch` as
-https://docs.spring.io/spring-boot/3.3/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
+https://docs.spring.io/spring-boot/3.4/reference/features/profiles.html#features.profiles.adding-active-profiles[Spring
Boot profile^]
for the Core application.
If needed, customize the `@Bean` declarations from
diff --git a/wa/starter/pom.xml b/wa/starter/pom.xml
index 781e85443a..62ab33d62f 100644
--- a/wa/starter/pom.xml
+++ b/wa/starter/pom.xml
@@ -532,20 +532,21 @@ under the License.
<id>debug</id>
<properties>
+ <maven.build.cache.skipCache>true</maven.build.cache.skipCache>
<maven.test.skip>true</maven.test.skip>
</properties>
<dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ </dependency>
+
<dependency>
<groupId>org.apache.syncope.common.keymaster.self</groupId>
<artifactId>syncope-common-keymaster-client-self</artifactId>
<version>${project.version}</version>
</dependency>
-
- <dependency>
- <groupId>com.h2database</groupId>
- <artifactId>h2</artifactId>
- </dependency>
</dependencies>
<build>
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 18fdb485ae..885f9944af 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
@@ -59,7 +59,6 @@ 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.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;
@@ -80,7 +79,6 @@ 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;
@@ -89,6 +87,7 @@ import
org.apereo.cas.trusted.authentication.api.MultifactorAuthenticationTrustR
import
org.apereo.cas.trusted.authentication.api.MultifactorAuthenticationTrustStorage;
import org.apereo.cas.util.LdapUtils;
import org.apereo.cas.util.crypto.CipherExecutor;
+import org.apereo.cas.util.spring.CasApplicationReadyListener;
import org.apereo.cas.webauthn.storage.WebAuthnCredentialRepository;
import org.ldaptive.ConnectionFactory;
import org.pac4j.core.client.Client;
@@ -101,7 +100,6 @@ import org.springframework.context.ApplicationContext;
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;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
@@ -232,10 +230,10 @@ public class WAContext {
}
@Bean
- @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
- @Lazy(false)
- public SamlIdPCasEventListener samlIdPCasEventListener() {
- return new WASamlIdPCasEventListener();
+ public CasApplicationReadyListener samlIdPCasEventListener() {
+ // skip generating IdP metadata at this stage, as the default
samlIdPCasEventListener bean is doing
+ return event -> {
+ };
}
@Bean
diff --git
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/WASamlIdPCasEventListener.java
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/WASamlIdPCasEventListener.java
deleted file mode 100644
index da1bcaf72c..0000000000
---
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/WASamlIdPCasEventListener.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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;
-
-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/resources/thymeleaf/templates/fragments/footer.html
b/wa/starter/src/main/resources/thymeleaf/templates/fragments/footer.html
index d991bf5eba..8ba1fd7b45 100644
--- a/wa/starter/src/main/resources/thymeleaf/templates/fragments/footer.html
+++ b/wa/starter/src/main/resources/thymeleaf/templates/fragments/footer.html
@@ -16,15 +16,21 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
-<footer class="py-4 d-flex flex-column justify-content-center cas-footer
text-center">
+<footer th:if="${'true' ==
#strings.defaultString(#themes.code('cas.footer.show'), 'true')}"
+ class="py-3 d-flex justify-content-center align-items-center
cas-footer">
<div class="pb-1 pt-1">
- Copyright © 2010-${year}
- <a href="http://www.apache.org/" target="_blank" rel="noopener
noreferrer">The Apache Software Foundation</a>.</strong>
- All rights reserved.
+ <span id="copyright" class="me-2 d-inline-block">Copyright © 2010-${year}
+ <a href="http://www.apache.org/" target="_blank" rel="noopener
noreferrer">The Apache Software Foundation</a>.</strong>
+ All rights reserved.
+ </span>
</div>
<div class="pb-1 pt-1">
- <span id="copyright" th:utext="#{copyright}" class="mr-2
d-inline-block">Copyright Date Apereo, Inc</span>
- <span class="mr-2 d-inline-block">Powered by <a
href="https://github.com/apereo/cas">Apereo CAS</a></span>
- <code class="version"
th:text="${T(org.apereo.cas.util.CasVersion).getVersion() + ' ' +
T(org.apereo.cas.util.CasVersion).getDateTime()}"></code>
+ <span id="copyright" th:utext="#{copyright}" class="me-2
d-inline-block">Copyright Date Apereo, Inc</span>
+ <span id="poweredBy" class="px-3 d-inline-block">
+ <span th:utext="#{poweredBy}">Powered by </span><a
href="https://github.com/apereo/cas">Apereo CAS</a>
+ </span>
+ <code class="version"
+ th:if="${'true' ==
#strings.defaultString(#themes.code('cas.footer.show-version'), 'true')}"
+ th:text="${T(org.apereo.cas.util.CasVersion).getVersion() + ' ' +
T(org.apereo.cas.util.CasVersion).getDateTime()}"></code>
</div>
</footer>
diff --git a/wa/starter/src/main/resources/wa.properties
b/wa/starter/src/main/resources/wa.properties
index 1291ccc994..8c2951a789 100644
--- a/wa/starter/src/main/resources/wa.properties
+++ b/wa/starter/src/main/resources/wa.properties
@@ -36,7 +36,7 @@ server.servlet.session.tracking-modes=COOKIE
spring.web.resources.static-locations=classpath:/thymeleaf/static,classpath:/syncope/static,classpath:/static
cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED
-management.endpoints.enabled-by-default=true
+management.endpoints.access.default=UNRESTRICTED
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
@@ -112,3 +112,28 @@ spring.mvc.pathmatch.matching-strategy=ant-path-matcher
# Disable CGLib Proxies
spring.aop.auto=true
spring.aop.proxy-target-class=false
+
+##
+# Metrics Configuration
+management.cloudwatch.metrics.export.enabled=false
+management.atlas.metrics.export.enabled=false
+management.datadog.metrics.export.enabled=false
+management.ganglia.metrics.export.enabled=false
+management.graphite.metrics.export.enabled=false
+management.influx.metrics.export.enabled=false
+management.jmx.metrics.export.enabled=false
+management.newrelic.metrics.export.enabled=false
+management.prometheus.metrics.export.enabled=false
+management.signalfx.metrics.export.enabled=false
+management.statsd.metrics.export.enabled=false
+management.wavefront.metrics.export.enabled=false
+management.elastic.metrics.export.enabled=false
+
+management.defaults.metrics.export.enabled=true
+
+management.metrics.enable.logback=false
+management.metrics.enable.process.files=true
+management.metrics.enable.system.cpu=true
+management.metrics.enable.process.cpu=true
+management.metrics.enable.process.uptime=true
+management.metrics.enable.process.start.time=true
diff --git
a/wa/starter/src/test/java/org/apache/syncope/wa/starter/AbstractTest.java
b/wa/starter/src/test/java/org/apache/syncope/wa/starter/AbstractTest.java
index f06aa39938..587079e08a 100644
--- a/wa/starter/src/test/java/org/apache/syncope/wa/starter/AbstractTest.java
+++ b/wa/starter/src/test/java/org/apache/syncope/wa/starter/AbstractTest.java
@@ -20,6 +20,7 @@ package org.apache.syncope.wa.starter;
import static org.awaitility.Awaitility.await;
+import com.okta.sdk.client.Client;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -40,7 +41,10 @@ import org.apereo.cas.authentication.principal.Service;
import org.apereo.cas.authentication.principal.attribute.PersonAttributeDao;
import
org.apereo.cas.authentication.principal.attribute.PersonAttributeDaoFilter;
import org.apereo.cas.authentication.principal.attribute.PersonAttributes;
+import
org.apereo.cas.persondir.PersonDirectoryAttributeRepositoryPlanConfigurer;
import org.apereo.cas.services.RegisteredService;
+import org.apereo.cas.util.spring.beans.BeanContainer;
+import org.apereo.cas.util.spring.beans.BeanSupplier;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@@ -205,11 +209,6 @@ public abstract class AbstractTest {
public AttributeDefinitionStore store(final Resource resource)
{
return this;
}
-
- @Override
- public AttributeDefinitionStore importStore(final
AttributeDefinitionStore definitionStore) {
- return this;
- }
};
}
@@ -224,6 +223,24 @@ public abstract class AbstractTest {
public PersonAttributeDao aggregatingAttributeRepository() {
return new DummyIPersonAttributeDao();
}
+
+ @Bean(name = "oktaPersonDirectoryClient")
+ @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
+ public Client oktaPersonDirectoryClient() {
+ return null;
+ }
+
+ @Bean(name = "oktaPersonAttributeDaos")
+ @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
+ public BeanContainer<PersonAttributeDao> oktaPersonAttributeDaos() {
+ return BeanContainer.empty();
+ }
+
+ @Bean(name = "oktaAttributeRepositoryPlanConfigurer")
+ @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
+ public PersonDirectoryAttributeRepositoryPlanConfigurer
oktaAttributeRepositoryPlanConfigurer() {
+ return
BeanSupplier.of(PersonDirectoryAttributeRepositoryPlanConfigurer.class).otherwiseProxy().get();
+ }
}
@LocalServerPort