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

mmoayyed 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 2fa7e28  Switch CAS to use 6.5.x / Spring Boot 2.6.x (#296)
2fa7e28 is described below

commit 2fa7e28874acfeca8b6124ffec94d7f0a2d0d9ba
Author: Misagh Moayyed <[email protected]>
AuthorDate: Fri Dec 10 09:18:45 2021 +0400

    Switch CAS to use 6.5.x / Spring Boot 2.6.x (#296)
    
    * switch cas to use 6.5 rc2
    
    * resume with boot 2.6 upgrade
    
    * update spring cloud gateway
    
    * upgrade to boot 2.6
    
    * Upgrading Groovy
    
    * Fix test cases; make sure exceptions are caught in SAML2 metadata 
generation process
    
    * assign a name to the syncope authn handler matching master-content and 
auth-module
    
    * Upgrading Tomcat
    
    * Upgrading Spring Boot
    
    * Upgrading Payara
    
    * Upgrading Wildfly
    
    * Getting Started Guide: reviewed for 3.0
    
    * [SYNCOPE-1651] Reviewing delegation validation logic
    
    * Upgrading gmavenplus-plugin
    
    * Reference Guide reviewed and compelted for 3.0 up to Customization
    
    * Typos in Reference Guide 3.0
    
    * [SYNCOPE-1654] Allowing to search realm by key or full path
    
    * Upgrading Swagger UI and Checkstyle
    
    * Upgrading Bouncycastle
    
    * Upgrading Wicket
    
    * upgrade to spring boot 2.6; fixes build issues
    
    * fix checkstyle
    
    * restore spring cloud contract wiremock version
    
    * update pac4j to match latest CAS 6.5 SNAPSHOT
    
    Co-authored-by: Francesco Chicchiriccò <[email protected]>
---
 client/idrepo/console/pom.xml                      |  2 +-
 .../console/src/main/resources/console.properties  |  1 +
 client/idrepo/enduser/pom.xml                      |  2 +-
 .../enduser/src/main/resources/enduser.properties  |  1 +
 .../enduser/SyncopeEnduserApplicationTest.java     |  2 -
 .../syncope/common/lib/types/AMEntitlement.java    |  2 +
 .../common/rest/api/service/OIDCJWKSService.java   |  8 +++
 .../apache/syncope/core/logic/OIDCJWKSLogic.java   |  8 +++
 .../core/rest/cxf/service/OIDCJWKSServiceImpl.java |  5 ++
 core/starter/pom.xml                               |  2 +-
 fit/build-tools/pom.xml                            |  2 +-
 .../src/main/resources/application.properties      |  1 +
 .../org/apache/syncope/fit/AbstractITCase.java     |  2 -
 .../src/main/resources/wa-embedded.properties      |  7 +++
 pom.xml                                            | 30 +++++++---
 sra/pom.xml                                        |  2 +-
 .../org/apache/syncope/sra/SecurityConfig.java     |  8 ++-
 .../bootstrap/SyncopeWABootstrapConfiguration.java | 32 ++++++-----
 .../syncope/wa/starter/SyncopeWAApplication.java   |  7 ++-
 .../wa/starter/config/SyncopeWAConfiguration.java  | 64 +++++++++++++---------
 .../starter/events/SyncopeWAEventRepository.java   |  5 +-
 .../oidc/SyncopeWAOIDCJWKSGeneratorService.java    | 24 +++++++-
 .../metadata/RestfulSamlIdPMetadataLocator.java    | 11 +++-
 wa/starter/src/main/resources/wa.properties        | 11 +++-
 .../audit/SyncopeWAAuditTrailManagerTest.java      |  2 +-
 .../src/test/resources/debug/wa-debug.properties   | 11 +++-
 26 files changed, 180 insertions(+), 72 deletions(-)

diff --git a/client/idrepo/console/pom.xml b/client/idrepo/console/pom.xml
index 31ca830..c0ba1d6 100644
--- a/client/idrepo/console/pom.xml
+++ b/client/idrepo/console/pom.xml
@@ -124,7 +124,7 @@ under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-slf4j18-impl</artifactId>
+      <artifactId>log4j-slf4j-impl</artifactId>
     </dependency>
     <dependency>
       <groupId>com.lmax</groupId>
diff --git a/client/idrepo/console/src/main/resources/console.properties 
b/client/idrepo/console/src/main/resources/console.properties
index bf17a78..723e8e3 100644
--- a/client/idrepo/console/src/main/resources/console.properties
+++ b/client/idrepo/console/src/main/resources/console.properties
@@ -17,6 +17,7 @@
 spring.application.name=Apache Syncope ${syncope.version} Console
 spring.groovy.template.check-template-location=false
 spring.main.banner-mode=log
+spring.main.allow-circular-references=true
 
 server.servlet.encoding.charset=UTF-8
 server.servlet.encoding.enabled=true
diff --git a/client/idrepo/enduser/pom.xml b/client/idrepo/enduser/pom.xml
index 6c127c7..f6b10eb 100644
--- a/client/idrepo/enduser/pom.xml
+++ b/client/idrepo/enduser/pom.xml
@@ -112,7 +112,7 @@ under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-slf4j18-impl</artifactId>
+      <artifactId>log4j-slf4j-impl</artifactId>
     </dependency>
     <dependency>
       <groupId>com.lmax</groupId>
diff --git a/client/idrepo/enduser/src/main/resources/enduser.properties 
b/client/idrepo/enduser/src/main/resources/enduser.properties
index a10cbce..a9f6930 100644
--- a/client/idrepo/enduser/src/main/resources/enduser.properties
+++ b/client/idrepo/enduser/src/main/resources/enduser.properties
@@ -17,6 +17,7 @@
 spring.application.name=Apache Syncope ${syncope.version} Enduser
 spring.groovy.template.check-template-location=false
 spring.main.banner-mode=log
+spring.main.allow-circular-references=true
 
 server.servlet.encoding.charset=UTF-8
 server.servlet.encoding.enabled=true
diff --git 
a/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/SyncopeEnduserApplicationTest.java
 
b/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/SyncopeEnduserApplicationTest.java
index fa678ca..b9227a7 100644
--- 
a/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/SyncopeEnduserApplicationTest.java
+++ 
b/client/idrepo/enduser/src/test/java/org/apache/syncope/client/enduser/SyncopeEnduserApplicationTest.java
@@ -25,8 +25,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
 import java.security.AccessControlException;
-import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import javax.ws.rs.BadRequestException;
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 1935279..305deca 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
@@ -88,6 +88,8 @@ public final class AMEntitlement {
 
     public static final String OIDC_JWKS_READ = "OIDC_JWKS_READ";
 
+    public static final String OIDC_JWKS_SET = "OIDC_JWKS_SET";
+
     public static final String OIDC_JWKS_DELETE = "OIDC_JWKS_DELETE";
 
     public static final String WA_CONFIG_LIST = "WA_CONFIG_LIST";
diff --git 
a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCJWKSService.java
 
b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCJWKSService.java
index e108097..53eb241 100644
--- 
a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCJWKSService.java
+++ 
b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCJWKSService.java
@@ -52,6 +52,13 @@ public interface OIDCJWKSService extends JAXRSService {
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, 
MediaType.APPLICATION_XML })
     OIDCJWKSTO get();
 
+    @ApiResponses(
+        @ApiResponse(responseCode = "204", description = "Operation was 
successful"))
+    @POST
+    @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, 
MediaType.APPLICATION_XML })
+    @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, 
MediaType.APPLICATION_XML })
+    void set(@NotNull OIDCJWKSTO entityTO);
+
     @ApiResponses({
         @ApiResponse(responseCode = "201",
                 description = "JWKS successfully created", headers = {
@@ -63,6 +70,7 @@ public interface OIDCJWKSService extends JAXRSService {
     @POST
     @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, 
MediaType.APPLICATION_XML })
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, 
MediaType.APPLICATION_XML })
+    @Path("new")
     Response generate(
             @NotNull @QueryParam("size") @DefaultValue("2048") int size,
             @NotNull @QueryParam("algorithm") @DefaultValue("RS256") 
JWSAlgorithm algorithm);
diff --git 
a/core/am/logic/src/main/java/org/apache/syncope/core/logic/OIDCJWKSLogic.java 
b/core/am/logic/src/main/java/org/apache/syncope/core/logic/OIDCJWKSLogic.java
index 0e03700..e105e82 100644
--- 
a/core/am/logic/src/main/java/org/apache/syncope/core/logic/OIDCJWKSLogic.java
+++ 
b/core/am/logic/src/main/java/org/apache/syncope/core/logic/OIDCJWKSLogic.java
@@ -76,4 +76,12 @@ public class OIDCJWKSLogic extends 
AbstractTransactionalLogic<OIDCJWKSTO> {
         }
         return binder.getOIDCJWKSTO(jwks);
     }
+
+    @PreAuthorize("hasRole('" + AMEntitlement.OIDC_JWKS_SET + "') "
+        + "or hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
+    public OIDCJWKSTO set(final OIDCJWKSTO entityTO) {
+        OIDCJWKS jwks = dao.get();
+        jwks.setJson(entityTO.getJson());
+        return binder.getOIDCJWKSTO(dao.save(jwks));
+    }
 }
diff --git 
a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCJWKSServiceImpl.java
 
b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCJWKSServiceImpl.java
index a4fcb71..ded23ea 100644
--- 
a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCJWKSServiceImpl.java
+++ 
b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCJWKSServiceImpl.java
@@ -41,6 +41,11 @@ public class OIDCJWKSServiceImpl extends AbstractService 
implements OIDCJWKSServ
     }
 
     @Override
+    public void set(final OIDCJWKSTO entityTO) {
+        logic.set(entityTO);
+    }
+
+    @Override
     public Response generate(final int size, final JWSAlgorithm algorithm) {
         OIDCJWKSTO jwks = logic.generate(size, algorithm);
         URI location = uriInfo.getAbsolutePathBuilder().build();
diff --git a/core/starter/pom.xml b/core/starter/pom.xml
index 0cee5ae..3bf08a6 100644
--- a/core/starter/pom.xml
+++ b/core/starter/pom.xml
@@ -83,7 +83,7 @@ under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-slf4j18-impl</artifactId>
+      <artifactId>log4j-slf4j-impl</artifactId>
     </dependency>
     <dependency>
       <groupId>com.lmax</groupId>
diff --git a/fit/build-tools/pom.xml b/fit/build-tools/pom.xml
index 2b5808c..a3319d9 100644
--- a/fit/build-tools/pom.xml
+++ b/fit/build-tools/pom.xml
@@ -203,7 +203,7 @@ under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-slf4j18-impl</artifactId>
+      <artifactId>log4j-slf4j-impl</artifactId>
     </dependency>
     <dependency>
       <groupId>com.lmax</groupId>
diff --git a/fit/build-tools/src/main/resources/application.properties 
b/fit/build-tools/src/main/resources/application.properties
index 9e8bdb3..6ee9cb4 100644
--- a/fit/build-tools/src/main/resources/application.properties
+++ b/fit/build-tools/src/main/resources/application.properties
@@ -17,6 +17,7 @@
 spring.application.name=Apache Syncope ${syncope.version} Build Tools
 spring.groovy.template.check-template-location=false
 #spring.main.banner-mode=log
+spring.main.allow-circular-references=true
 
 server.servlet.encoding.charset=UTF-8
 server.servlet.encoding.enabled=true
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index c52de8a..933e1d2 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -18,8 +18,6 @@
  */
 package org.apache.syncope.fit;
 
-import static org.apache.syncope.fit.AbstractUIITCase.ANONYMOUS_KEY;
-import static org.apache.syncope.fit.AbstractUIITCase.ANONYMOUS_UNAME;
 import static org.awaitility.Awaitility.await;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
diff --git a/fit/wa-reference/src/main/resources/wa-embedded.properties 
b/fit/wa-reference/src/main/resources/wa-embedded.properties
index 87fae00..6eb99fd 100644
--- a/fit/wa-reference/src/main/resources/wa-embedded.properties
+++ b/fit/wa-reference/src/main/resources/wa-embedded.properties
@@ -14,6 +14,8 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+spring.main.allow-circular-references=true
+
 keymaster.address=http://localhost:9080/syncope/rest/keymaster
 keymaster.username=${anonymousUser}
 keymaster.password=${anonymousKey}
@@ -30,3 +32,8 @@ 
cas.authn.saml-idp.metadata.http.metadata-backup-location=file:${conf.directory}
 cas.authn.oidc.core.issuer=${cas.server.prefix}/oidc
 
 service.discovery.address=http://localhost:9080/syncope-wa/
+
+##
+# Default strategy for matching request paths against
+# registered Spring MVC handler mappings
+spring.mvc.pathmatch.matching-strategy=ant-path-matcher
diff --git a/pom.xml b/pom.xml
index 2a756cc..6f4a6e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -409,8 +409,8 @@ under the License.
 
     <jackson.version>2.13.0</jackson.version>
 
-    <spring-boot.version>2.5.7</spring-boot.version>
-    <spring-cloud-gateway.version>3.0.5</spring-cloud-gateway.version>
+    <spring-boot.version>2.6.1</spring-boot.version>
+    <spring-cloud-gateway.version>3.1.0</spring-cloud-gateway.version>
 
     <openjpa.version>3.2.0</openjpa.version>
     <hikaricp.version>5.0.0</hikaricp.version>
@@ -428,7 +428,7 @@ under the License.
 
     <camel.version>3.13.0</camel.version>
 
-    <slf4j.version>2.0.0-alpha5</slf4j.version>
+    <slf4j.version>1.7.32</slf4j.version>
 
     <elasticsearch.version>7.15.2</elasticsearch.version>
 
@@ -446,9 +446,9 @@ under the License.
 
     <modernizer-maven.version>2.3.0</modernizer-maven.version>
 
-    <pac4j.version>5.1.4</pac4j.version>
+    <pac4j.version>5.2.0</pac4j.version>
 
-    <cas.version>6.4.2</cas.version>
+    <cas.version>6.5.0-SNAPSHOT</cas.version>
     <cas-client.version>3.6.2</cas-client.version>
 
     <h2.version>1.4.200</h2.version>
@@ -1740,7 +1740,7 @@ under the License.
       </dependency>
       <dependency>
         <groupId>org.apache.logging.log4j</groupId>
-        <artifactId>log4j-slf4j18-impl</artifactId>
+        <artifactId>log4j-slf4j-impl</artifactId>
         <version>${log4j.version}</version>
       </dependency>
       <dependency>
@@ -1888,9 +1888,7 @@ under the License.
       <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-contract-wiremock</artifactId>
-        <version>3.0.4</version>
-        <!-- unfortunately, not always aligned with spring-cloud-gateway -->
-        <!--<version>${spring-cloud-gateway.version}</version>-->
+        <version>${spring-cloud-gateway.version}</version>
         <scope>test</scope>
       </dependency>
 
@@ -1922,6 +1920,13 @@ under the License.
         <enabled>true</enabled>
       </releases>
     </repository>
+    <repository>
+      <id>spring</id>
+      <url>https://repo.spring.io/milestone</url>
+      <releases>
+        <enabled>true</enabled>
+      </releases>
+    </repository>
   </repositories>
 
   <pluginRepositories>
@@ -1955,6 +1960,13 @@ under the License.
         <enabled>true</enabled>
       </snapshots>
     </pluginRepository>
+    <pluginRepository>
+      <id>spring</id>
+      <url>https://repo.spring.io/milestone</url>
+      <releases>
+        <enabled>true</enabled>
+      </releases>
+    </pluginRepository>
   </pluginRepositories>
 
   <build>
diff --git a/sra/pom.xml b/sra/pom.xml
index cfa3a79..8a575db 100644
--- a/sra/pom.xml
+++ b/sra/pom.xml
@@ -130,7 +130,7 @@ under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
-      <artifactId>log4j-slf4j18-impl</artifactId>
+      <artifactId>log4j-slf4j-impl</artifactId>
     </dependency>
     <dependency>
       <groupId>com.lmax</groupId>
diff --git a/sra/src/main/java/org/apache/syncope/sra/SecurityConfig.java 
b/sra/src/main/java/org/apache/syncope/sra/SecurityConfig.java
index 139780d..e3e75b6 100644
--- a/sra/src/main/java/org/apache/syncope/sra/SecurityConfig.java
+++ b/sra/src/main/java/org/apache/syncope/sra/SecurityConfig.java
@@ -63,6 +63,7 @@ import 
org.springframework.security.oauth2.client.registration.ClientRegistratio
 import 
org.springframework.security.oauth2.client.registration.InMemoryReactiveClientRegistrationRepository;
 import org.springframework.security.oauth2.core.AuthorizationGrantType;
 import org.springframework.security.oauth2.core.OAuth2TokenValidator;
+import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtValidators;
 import org.springframework.security.oauth2.jwt.MappedJwtClaimSetConverter;
@@ -146,8 +147,11 @@ public class SecurityConfig {
     @ConditionalOnMissingBean
     @ConditionalOnProperty(prefix = SRAProperties.PREFIX, name = 
SRAProperties.AM_TYPE, havingValue = "OIDC")
     public ReactiveJwtDecoder oidcJWTDecoder() {
-        NimbusReactiveJwtDecoder jwtDecoder = 
NimbusReactiveJwtDecoder.withJwkSetUri(
-                
oidcClientRegistrationRepository().iterator().next().getProviderDetails().getJwkSetUri()).build();
+        String jwkSetUri = 
oidcClientRegistrationRepository().iterator().next().getProviderDetails().getJwkSetUri();
+        NimbusReactiveJwtDecoder jwtDecoder = 
NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri)
+            .jwsAlgorithm(SignatureAlgorithm.RS256)
+            .jwsAlgorithm(SignatureAlgorithm.RS512)
+            .build();
         jwtDecoder.setJwtValidator(oidcJWTValidator());
         jwtDecoder.setClaimSetConverter(jwtClaimSetConverter());
         return jwtDecoder;
diff --git 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWABootstrapConfiguration.java
 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWABootstrapConfiguration.java
index 1d1dc2dd..d167e80 100644
--- 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWABootstrapConfiguration.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/SyncopeWABootstrapConfiguration.java
@@ -30,23 +30,29 @@ import 
org.springframework.context.annotation.PropertySource;
 @PropertySource(value = "file:${conf.directory}/wa.properties", 
ignoreResourceNotFound = true)
 public class SyncopeWABootstrapConfiguration {
 
-    @Value("${wa.anonymousUser}")
-    private String anonymousUser;
+    @Configuration(proxyBeanMethods = false)
+    public static class WAClientConfiguration {
+        @Value("${wa.anonymousUser}")
+        private String anonymousUser;
 
-    @Value("${wa.anonymousKey}")
-    private String anonymousKey;
+        @Value("${wa.anonymousKey}")
+        private String anonymousKey;
 
-    @Value("${wa.useGZIPCompression:true}")
-    private boolean useGZIPCompression;
+        @Value("${wa.useGZIPCompression:true}")
+        private boolean useGZIPCompression;
 
-    @Bean
-    public WARestClient waRestClient() {
-        return new WARestClient(anonymousUser, anonymousKey, 
useGZIPCompression);
+        @Bean
+        public WARestClient waRestClient() {
+            return new WARestClient(anonymousUser, anonymousKey, 
useGZIPCompression);
+        }
     }
 
-    @Autowired
-    @Bean
-    public PropertySourceLocator configPropertySourceLocator(final 
WARestClient waRestClient) {
-        return new SyncopeWAPropertySourceLocator(waRestClient);
+    @Configuration(proxyBeanMethods = false)
+    public static class PropertySourceConfiguration {
+        @Autowired
+        @Bean
+        public PropertySourceLocator configPropertySourceLocator(final 
WARestClient waRestClient) {
+            return new SyncopeWAPropertySourceLocator(waRestClient);
+        }
     }
 }
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAApplication.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAApplication.java
index 7c4b0fd..6e83d8f 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAApplication.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAApplication.java
@@ -84,8 +84,8 @@ public class SyncopeWAApplication extends 
SpringBootServletInitializer {
 
     public static void main(final String[] args) {
         new SpringApplicationBuilder(SyncopeWAApplication.class).
-                properties("spring.config.name:wa").
-                build().run(args);
+            properties(Map.of("spring.config.name", "wa", 
"spring.cloud.bootstrap.name", "wa")).
+            build().run(args);
     }
 
     @Autowired
@@ -96,7 +96,8 @@ public class SyncopeWAApplication extends 
SpringBootServletInitializer {
 
     @Override
     protected SpringApplicationBuilder configure(final 
SpringApplicationBuilder builder) {
-        return builder.properties(Map.of("spring.config.name", 
"wa")).sources(SyncopeWAApplication.class);
+        return builder.properties(Map.of("spring.config.name", "wa",
+            "spring.cloud.bootstrap.name", 
"wa")).sources(SyncopeWAApplication.class);
     }
 
     /**
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/SyncopeWAConfiguration.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/SyncopeWAConfiguration.java
index b8bd1ed..ccb9625 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/SyncopeWAConfiguration.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/SyncopeWAConfiguration.java
@@ -27,9 +27,12 @@ import io.swagger.v3.oas.models.info.Info;
 import io.swagger.v3.oas.models.security.SecurityScheme;
 import java.time.LocalDate;
 import java.time.ZoneId;
-import java.util.Collection;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
 import org.apache.syncope.common.keymaster.client.api.startstop.KeymasterStart;
@@ -70,11 +73,12 @@ import 
org.apereo.cas.audit.AuditTrailExecutionPlanConfigurer;
 import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationService;
 import org.apereo.cas.configuration.CasConfigurationProperties;
 import 
org.apereo.cas.configuration.model.support.mfa.u2f.U2FCoreMultifactorAuthenticationProperties;
-import org.apereo.cas.oidc.jwks.OidcJsonWebKeystoreGeneratorService;
+import org.apereo.cas.oidc.jwks.generator.OidcJsonWebKeystoreGeneratorService;
 import 
org.apereo.cas.otp.repository.credentials.OneTimeTokenCredentialRepository;
 import org.apereo.cas.otp.repository.token.OneTimeTokenRepository;
 import org.apereo.cas.services.ServiceRegistryExecutionPlanConfigurer;
 import org.apereo.cas.services.ServiceRegistryListener;
+import org.apereo.cas.services.web.CasThymeleafLoginFormDirector;
 import org.apereo.cas.support.events.CasEventRepository;
 import org.apereo.cas.support.events.CasEventRepositoryFilter;
 import 
org.apereo.cas.support.pac4j.authentication.DelegatedClientFactoryCustomizer;
@@ -83,8 +87,10 @@ import 
org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGenerat
 import org.apereo.cas.support.saml.idp.metadata.locator.SamlIdPMetadataLocator;
 import org.apereo.cas.util.DateTimeUtils;
 import org.apereo.cas.util.crypto.CipherExecutor;
+import org.apereo.cas.web.flow.CasWebflowExecutionPlan;
 import org.apereo.cas.webauthn.storage.WebAuthnCredentialRepository;
 import org.pac4j.core.client.Client;
+import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import 
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -96,31 +102,21 @@ import 
org.springframework.context.annotation.Configuration;
 @Configuration(value = "SyncopeWAConfiguration", proxyBeanMethods = false)
 public class SyncopeWAConfiguration {
 
-    @Autowired
-    private CasConfigurationProperties casProperties;
-
-    @Autowired
-    private ConfigurableApplicationContext ctx;
-
-    @Autowired
-    @Qualifier("serviceRegistryListeners")
-    private Collection<ServiceRegistryListener> serviceRegistryListeners;
-
-    private String version() {
+    private static String version(final ConfigurableApplicationContext ctx) {
         return ctx.getEnvironment().getProperty("version");
     }
 
     @Bean
-    public OpenAPI casSwaggerOpenApi() {
+    public OpenAPI casSwaggerOpenApi(final ConfigurableApplicationContext ctx) 
{
         return new OpenAPI().
                 info(new Info().
                         title("Apache Syncope").
-                        description("Apache Syncope " + version()).
+                        description("Apache Syncope " + version(ctx)).
                         contact(new Contact().
                                 name("The Apache Syncope community").
                                 email("[email protected]").
                                 url("https://syncope.apache.org";)).
-                        version(version())).
+                        version(version(ctx))).
                 schemaRequirement("BasicAuthentication",
                         new 
SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("basic")).
                 schemaRequirement("Bearer",
@@ -165,7 +161,7 @@ public class SyncopeWAConfiguration {
 
     @ConditionalOnMissingBean
     @Bean
-    public RegisteredServiceMapper registeredServiceMapper() {
+    public RegisteredServiceMapper registeredServiceMapper(final 
ConfigurableApplicationContext ctx) {
         Map<String, AuthMapper> authPolicyConfMappers = new HashMap<>();
         ctx.getBeansOfType(AuthMapper.class).forEach((name, bean) -> {
             AuthMapFor authMapFor = ctx.findAnnotationOnBean(name, 
AuthMapFor.class);
@@ -209,10 +205,15 @@ public class SyncopeWAConfiguration {
     @Autowired
     @Bean
     public ServiceRegistryExecutionPlanConfigurer 
syncopeServiceRegistryConfigurer(
-            final WARestClient restClient, final RegisteredServiceMapper 
registeredServiceMapper) {
+            final ConfigurableApplicationContext ctx,
+            final WARestClient restClient,
+            final RegisteredServiceMapper registeredServiceMapper,
+            @Qualifier("serviceRegistryListeners")
+            final ObjectProvider<List<ServiceRegistryListener>> 
serviceRegistryListeners) {
 
         SyncopeWAServiceRegistry registry = new SyncopeWAServiceRegistry(
-                restClient, registeredServiceMapper, ctx, 
serviceRegistryListeners);
+                restClient, registeredServiceMapper, ctx,
+                
Optional.ofNullable(serviceRegistryListeners.getIfAvailable()).orElseGet(ArrayList::new));
         return plan -> plan.registerServiceRegistry(registry);
     }
 
@@ -260,9 +261,10 @@ public class SyncopeWAConfiguration {
         return new SyncopeWASAML2ClientCustomizer(restClient);
     }
 
-    @Autowired
     @Bean
-    public OneTimeTokenRepository 
oneTimeTokenAuthenticatorTokenRepository(final WARestClient restClient) {
+    public OneTimeTokenRepository oneTimeTokenAuthenticatorTokenRepository(
+        final CasConfigurationProperties casProperties,
+        final WARestClient restClient) {
         return new SyncopeWAGoogleMfaAuthTokenRepository(
                 restClient, 
casProperties.getAuthn().getMfa().getGauth().getCore().getTimeStepSize());
     }
@@ -277,7 +279,9 @@ public class SyncopeWAConfiguration {
 
     @Autowired
     @Bean
-    public OidcJsonWebKeystoreGeneratorService 
oidcJsonWebKeystoreGeneratorService(final WARestClient restClient) {
+    public OidcJsonWebKeystoreGeneratorService 
oidcJsonWebKeystoreGeneratorService(
+        final ConfigurableApplicationContext ctx,
+        final WARestClient restClient) {
         int size = ctx.getEnvironment().
                 getProperty("cas.authn.oidc.jwks.size", int.class, 2048);
         JWSAlgorithm algorithm = ctx.getEnvironment().
@@ -287,15 +291,17 @@ public class SyncopeWAConfiguration {
 
     @RefreshScope
     @Bean
-    @Autowired
-    public WebAuthnCredentialRepository webAuthnCredentialRepository(final 
WARestClient restClient) {
+    public WebAuthnCredentialRepository webAuthnCredentialRepository(
+        final CasConfigurationProperties casProperties,
+        final WARestClient restClient) {
         return new SyncopeWAWebAuthnCredentialRepository(casProperties, 
restClient);
     }
 
     @Bean
-    @Autowired
     @RefreshScope
-    public U2FDeviceRepository u2fDeviceRepository(final WARestClient 
restClient) {
+    public U2FDeviceRepository u2fDeviceRepository(
+        final CasConfigurationProperties casProperties,
+        final WARestClient restClient) {
         U2FCoreMultifactorAuthenticationProperties u2f = 
casProperties.getAuthn().getMfa().getU2f().getCore();
         LocalDate expirationDate = LocalDate.now(ZoneId.systemDefault()).
                 minus(u2f.getExpireDevices(), 
DateTimeUtils.toChronoUnit(u2f.getExpireDevicesTimeUnit()));
@@ -333,4 +339,10 @@ public class SyncopeWAConfiguration {
     public KeymasterStop keymasterStop() {
         return new KeymasterStop(NetworkService.Type.WA);
     }
+
+    @Bean
+    public CasThymeleafLoginFormDirector casThymeleafLoginFormDirector(
+        @Qualifier("casWebflowExecutionPlan") final CasWebflowExecutionPlan 
webflowExecutionPlan) {
+        return new CasThymeleafLoginFormDirector(webflowExecutionPlan);
+    }
 }
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepository.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepository.java
index c89eea0..69fd679 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepository.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/events/SyncopeWAEventRepository.java
@@ -20,10 +20,11 @@ package org.apache.syncope.wa.starter.events;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.stream.Stream;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.audit.AuditEntry;
@@ -100,7 +101,7 @@ public class SyncopeWAEventRepository extends 
AbstractCasEventRepository {
     }
 
     @Override
-    public Collection<? extends CasEvent> load() {
+    public Stream<? extends CasEvent> load() {
         throw new UnsupportedOperationException("Fetching authentication 
events from WA is not supported");
     }
 }
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/SyncopeWAOIDCJWKSGeneratorService.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/SyncopeWAOIDCJWKSGeneratorService.java
index 23f254d..830733a 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/SyncopeWAOIDCJWKSGeneratorService.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/oidc/SyncopeWAOIDCJWKSGeneratorService.java
@@ -18,7 +18,11 @@
  */
 package org.apache.syncope.wa.starter.oidc;
 
+import org.apereo.cas.oidc.jwks.generator.OidcJsonWebKeystoreGeneratorService;
+
 import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+
 import javax.ws.rs.core.Response;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.OIDCJWKSTO;
@@ -26,7 +30,8 @@ import 
org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.JWSAlgorithm;
 import org.apache.syncope.common.rest.api.service.OIDCJWKSService;
 import org.apache.syncope.wa.bootstrap.WARestClient;
-import org.apereo.cas.oidc.jwks.OidcJsonWebKeystoreGeneratorService;
+import org.jose4j.jwk.JsonWebKey;
+import org.jose4j.jwk.JsonWebKeySet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.core.io.ByteArrayResource;
@@ -51,6 +56,23 @@ public class SyncopeWAOIDCJWKSGeneratorService implements 
OidcJsonWebKeystoreGen
     }
 
     @Override
+    public JsonWebKeySet store(final JsonWebKeySet jsonWebKeySet) throws 
Exception {
+        if (!WARestClient.isReady()) {
+            throw new RuntimeException("Syncope core is not yet ready");
+        }
+        OIDCJWKSService service = 
waRestClient.getSyncopeClient().getService(OIDCJWKSService.class);
+        OIDCJWKSTO to = new OIDCJWKSTO();
+        
to.setJson(jsonWebKeySet.toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE));
+        service.set(to);
+        return jsonWebKeySet;
+    }
+
+    @Override
+    public Optional<Resource> find() {
+        return Optional.of(generate());
+    }
+
+    @Override
     public Resource generate() {
         if (!WARestClient.isReady()) {
             throw new RuntimeException("Syncope core is not yet ready");
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
index 88568e8..25352ce 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/saml/idp/metadata/RestfulSamlIdPMetadataLocator.java
@@ -87,11 +87,16 @@ public class RestfulSamlIdPMetadataLocator extends 
AbstractSamlIdPMetadataLocato
 
             LOG.warn("Not a valid SAML2 IdP metadata document");
             return null;
-        } catch (SyncopeClientException e) {
-            if (e.getType() == ClientExceptionType.NotFound) {
+        } catch (Exception e) {
+            if (e instanceof SyncopeClientException
+                && ((SyncopeClientException) e).getType() == 
ClientExceptionType.NotFound) {
                 LOG.info(e.getMessage());
             } else {
-                LOG.error("While fetching SAML2 IdP metadata", e);
+                if (LOG.isDebugEnabled()) {
+                    LOG.error("While fetching SAML2 IdP metadata", e);
+                } else {
+                    LOG.error("While fetching SAML2 IdP metadata: " + 
e.getMessage());
+                }
             }
         }
 
diff --git a/wa/starter/src/main/resources/wa.properties 
b/wa/starter/src/main/resources/wa.properties
index 51840bd..281f148 100644
--- a/wa/starter/src/main/resources/wa.properties
+++ b/wa/starter/src/main/resources/wa.properties
@@ -17,6 +17,7 @@
 spring.application.name=Apache Syncope ${syncope.version} WA
 spring.groovy.template.check-template-location=false
 spring.main.banner-mode=log
+spring.main.allow-circular-references=true
 
 version=${syncope.version}
 
@@ -79,7 +80,7 @@ 
cas.authn.saml-idp.metadata.http.metadata-backup-location=file:${conf.directory}
 cas.authn.oidc.core.issuer=${cas.server.prefix}/oidc
 
cas.authn.oidc.discovery.id-token-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
 
cas.authn.oidc.discovery.user-info-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
-cas.authn.oauth.user-profile-view-type=FLAT
+cas.authn.oauth.core.user-profile-view-type=FLAT
 
 # Disable access to the login endpoint
 # if no target application is specified.
@@ -102,4 +103,10 @@ 
cas.authn.mfa.web-authn.core.application-id=https://localhost:8443
 cas.authn.mfa.web-authn.core.relying-party-name=Syncope 
 cas.authn.mfa.web-authn.core.relying-party-id=syncope.apache.org
 
-cas.authn.syncope.url=${cas.server.name}/syncope/rest/
+cas.authn.syncope.url=${cas.server.name}/syncope
+cas.authn.syncope.name=DefaultSyncopeAuthModule
+
+##
+# Default strategy for matching request paths against
+# registered Spring MVC handler mappings
+spring.mvc.pathmatch.matching-strategy=ant-path-matcher
diff --git 
a/wa/starter/src/test/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManagerTest.java
 
b/wa/starter/src/test/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManagerTest.java
index 7c2a352..9d2f878 100644
--- 
a/wa/starter/src/test/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManagerTest.java
+++ 
b/wa/starter/src/test/java/org/apache/syncope/wa/starter/audit/SyncopeWAAuditTrailManagerTest.java
@@ -50,7 +50,7 @@ public class SyncopeWAAuditTrailManagerTest extends 
AbstractTest {
     @Test
     public void saveAuditRecord() {
         AuditActionContext audit = new AuditActionContext("principal", 
"resourceOperatedUpon", "actionPerformed",
-                "applicationCode", new Date(), "clientIpAddress", 
"serverIpAddress");
+                "applicationCode", new Date(), "clientIpAddress", 
"serverIpAddress", "userAgent");
         SyncopeWAAuditTrailManager auditTrailManager = new 
SyncopeWAAuditTrailManager(getWaRestClient());
         auditTrailManager.saveAuditRecord(audit);
         verify(loggerService).create(any(AuditEntry.class));
diff --git a/wa/starter/src/test/resources/debug/wa-debug.properties 
b/wa/starter/src/test/resources/debug/wa-debug.properties
index fdcb208..243d97d 100644
--- a/wa/starter/src/test/resources/debug/wa-debug.properties
+++ b/wa/starter/src/test/resources/debug/wa-debug.properties
@@ -14,6 +14,8 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+spring.main.allow-circular-references=true
+
 keymaster.address=http://localhost:9080/syncope/rest/keymaster
 keymaster.username=${anonymousUser}
 keymaster.password=${anonymousKey}
@@ -21,4 +23,11 @@ keymaster.password=${anonymousKey}
 cas.server.name=http://localhost:8080
 cas.server.prefix=${cas.server.name}/syncope-wa
 cas.authn.accept.users=admin::password
-cas.authn.syncope.url=http://localhost:9080/syncope/rest/
+
+cas.authn.syncope.url=http://localhost:9080/syncope
+cas.authn.syncope.name=DefaultSyncopeAuthModule
+
+##
+# Default strategy for matching request paths against
+# registered Spring MVC handler mappings
+spring.mvc.pathmatch.matching-strategy=ant-path-matcher

Reply via email to