You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2026/04/29 06:31:18 UTC

(syncope) branch 4_1_X updated (f9f52e43ae -> 68338fed48)

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

ilgrosso pushed a change to branch 4_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


    from f9f52e43ae [SYNCOPE-1961] Implement MFA (#1360)
     new 28a07d4688 Bump org.openapitools:openapi-generator-maven-plugin
     new 2c882c4ff1 Bump org.postgresql:postgresql from 42.7.10 to 42.7.11
     new 2e2d4ecde5 Bump swagger-core.version from 2.2.48 to 2.2.49
     new 68338fed48 Restoring feature from SYNCOPE-1903

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../common/rest/api/service/UserService.java       | 16 ++++++++++++
 .../org/apache/syncope/core/logic/UserLogic.java   | 27 ++++++++++++++++++++
 .../org/apache/syncope/core/logic/UserLogicOp.java |  2 ++
 .../core/rest/cxf/service/UserServiceImpl.java     |  5 ++++
 .../org/apache/syncope/fit/core/UserITCase.java    | 29 ++++++++++++++++++++++
 pom.xml                                            |  6 ++---
 6 files changed, 82 insertions(+), 3 deletions(-)


(syncope) 04/04: Restoring feature from SYNCOPE-1903

Posted by il...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 4_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git

commit 68338fed482577a01824b8d9990b20f770dfc23a
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Wed Apr 29 08:31:08 2026 +0200

    Restoring feature from SYNCOPE-1903
---
 .../common/rest/api/service/UserService.java       | 16 ++++++++++++
 .../org/apache/syncope/core/logic/UserLogic.java   | 27 ++++++++++++++++++++
 .../org/apache/syncope/core/logic/UserLogicOp.java |  2 ++
 .../core/rest/cxf/service/UserServiceImpl.java     |  5 ++++
 .../org/apache/syncope/fit/core/UserITCase.java    | 29 ++++++++++++++++++++++
 5 files changed, 79 insertions(+)

diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
index 8d8fc8fec6..f7cbc3bd6f 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
@@ -34,6 +34,7 @@ import jakarta.ws.rs.PATCH;
 import jakarta.ws.rs.POST;
 import jakarta.ws.rs.Path;
 import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
 import jakarta.ws.rs.core.HttpHeaders;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Response;
@@ -194,4 +195,19 @@ public interface UserService extends AnyService<UserTO> {
     @Produces({ MediaType.APPLICATION_JSON })
     @Consumes({ MediaType.APPLICATION_JSON })
     Response status(@NotNull StatusR updateReq);
+
+    /**
+     * Provides answer for the security question configured for user matching the given username, if any.
+     * If provided answer matches the one stored for that user, check completes successfully,
+     * otherwise an error is returned.
+     *
+     * @param username username for which the security answer is provided
+     * @param securityAnswer actual answer text
+     */
+    @ApiResponses(
+            @ApiResponse(responseCode = "204", description = "Operation was successful"))
+    @POST
+    @Path("verifySecurityAnswer")
+    @Produces({ MediaType.APPLICATION_JSON })
+    void verifySecurityAnswer(@NotNull @QueryParam("username") String username, String securityAnswer);
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
index eb94b7e0e2..18b4124df8 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
@@ -24,6 +24,8 @@ import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
+import org.apache.syncope.common.keymaster.client.api.StandardConfParams;
+import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.request.PasswordPatch;
 import org.apache.syncope.common.lib.request.StatusR;
 import org.apache.syncope.common.lib.request.StringPatchItem;
@@ -34,6 +36,7 @@ import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.core.persistence.api.EncryptorManager;
@@ -289,4 +292,28 @@ public class UserLogic extends AbstractUserLogic implements UserLogicOp {
     public ProvisioningResult<UserTO> delete(final String key, final boolean nullPriorityAsync) {
         return doDelete(binder.getUserTO(key), false, nullPriorityAsync);
     }
+
+    @PreAuthorize("hasRole('" + IdRepoEntitlement.USER_SEARCH + "')")
+    @Transactional(readOnly = true)
+    @Override
+    public void verifySecurityAnswer(final String username, final String securityAnswer) {
+        if (!confParamOps.get(
+                AuthContextUtils.getDomain(), StandardConfParams.PASSWORD_RESET_ALLOWED, false, boolean.class)) {
+
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.DelegatedAdministration);
+            sce.getElements().add("Password reset forbidden by configuration");
+            throw sce;
+        }
+
+        User user = userDAO.findByUsername(username).
+                orElseThrow(() -> new NotFoundException("User " + username));
+
+        if (confParamOps.get(
+                AuthContextUtils.getDomain(), StandardConfParams.PASSWORD_RESET_SECURITY_QUESTION, false, boolean.class)
+                && (securityAnswer == null || !encryptorManager.getInstance().
+                        verify(securityAnswer, user.getCipherAlgorithm(), user.getSecurityAnswer()))) {
+
+            throw SyncopeClientException.build(ClientExceptionType.InvalidSecurityAnswer);
+        }
+    }
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogicOp.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogicOp.java
index 5ee4333c24..78a78b0909 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogicOp.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/UserLogicOp.java
@@ -27,4 +27,6 @@ import org.apache.syncope.common.lib.to.UserTO;
 public interface UserLogicOp extends AnyCRUDLogicOp<UserTO, UserCR, UserUR> {
 
     ProvisioningResult<UserTO> status(StatusR statusR, boolean nullPriorityAsync);
+
+    void verifySecurityAnswer(String username, String securityAnswer);
 }
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
index 9dbed5c4fd..2cfd4d152d 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
@@ -82,4 +82,9 @@ public class UserServiceImpl extends AbstractAnyService<UserTO, UserCR, UserUR>
         ProvisioningResult<UserTO> updated = logic.status(statusR, isNullPriorityAsync());
         return modificationResponse(updated);
     }
+
+    @Override
+    public void verifySecurityAnswer(final String username, final String securityAnswer) {
+        logic.verifySecurityAnswer(username, securityAnswer);
+    }
 }
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
index db0693a71f..2cafee9305 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
@@ -47,6 +47,7 @@ import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.client.lib.batch.BatchRequest;
+import org.apache.syncope.common.keymaster.client.api.StandardConfParams;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
@@ -1393,4 +1394,32 @@ public class UserITCase extends AbstractITCase {
         UserTO userTO = createUser(userCR).getEntity();
         assertNotNull(userTO.getKey());
     }
+
+    @Test
+    public void verifySecurityAnswer() {
+        // 0. ensure that password request DOES require security question
+        confParamOps.set(SyncopeConstants.MASTER_DOMAIN, StandardConfParams.PASSWORD_RESET_SECURITY_QUESTION, true);
+
+        // 1. create an user with security question and answer
+        UserCR user = UserITCase.getUniqueSample("pwdReset@syncope.apache.org");
+        user.setSecurityQuestion("887028ea-66fc-41e7-b397-620d7ea6dfbb");
+        user.setSecurityAnswer("Rossi");
+        createUser(user);
+
+        // 2. verify wrong security answer
+        try {
+            ADMIN_CLIENT.getService(UserService.class).verifySecurityAnswer(user.getUsername(), "WRONG");
+            fail("This should not happen");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidSecurityAnswer, e.getType());
+        }
+
+        // 3. verify the expected security answer
+        try {
+            ADMIN_CLIENT.getService(UserService.class).verifySecurityAnswer(user.getUsername(), "Rossi");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidSecurityAnswer, e.getType());
+            fail("This should not happen");
+        }
+    }
 }


(syncope) 01/04: Bump org.openapitools:openapi-generator-maven-plugin

Posted by il...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 4_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git

commit 28a07d4688e3f6f21d600c8eb8ca4b00dda15769
Author: dependabot[bot] <49...@users.noreply.github.com>
AuthorDate: Tue Apr 28 22:47:10 2026 +0000

    Bump org.openapitools:openapi-generator-maven-plugin
    
    Bumps org.openapitools:openapi-generator-maven-plugin from 7.21.0 to 7.22.0.
    
    ---
    updated-dependencies:
    - dependency-name: org.openapitools:openapi-generator-maven-plugin
      dependency-version: 7.22.0
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 79ebf6f615..196ec7d7d9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1759,7 +1759,7 @@ under the License.
         <plugin>
           <groupId>org.openapitools</groupId>
           <artifactId>openapi-generator-maven-plugin</artifactId>
-          <version>7.21.0</version>
+          <version>7.22.0</version>
         </plugin>
 
         <plugin>


(syncope) 02/04: Bump org.postgresql:postgresql from 42.7.10 to 42.7.11

Posted by il...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 4_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git

commit 2c882c4ff1cfc13e9716dd5de16c07c0d099d359
Author: dependabot[bot] <49...@users.noreply.github.com>
AuthorDate: Tue Apr 28 22:38:49 2026 +0000

    Bump org.postgresql:postgresql from 42.7.10 to 42.7.11
    
    Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.10 to 42.7.11.
    - [Release notes](https://github.com/pgjdbc/pgjdbc/releases)
    - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.7.10...REL42.7.11)
    
    ---
    updated-dependencies:
    - dependency-name: org.postgresql:postgresql
      dependency-version: 42.7.11
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 196ec7d7d9..7d95d3a264 100644
--- a/pom.xml
+++ b/pom.xml
@@ -537,7 +537,7 @@ under the License.
     <docker.oracle.version>23-slim-faststart</docker.oracle.version>
     <docker.neo4j.version>5.26</docker.neo4j.version>
 
-    <jdbc.postgresql.version>42.7.10</jdbc.postgresql.version>
+    <jdbc.postgresql.version>42.7.11</jdbc.postgresql.version>
     <jdbc.mysql.version>9.7.0</jdbc.mysql.version>
     <jdbc.mariadb.version>3.5.8</jdbc.mariadb.version>
     <jdbc.oracle.version>23.26.1.0.0</jdbc.oracle.version>


(syncope) 03/04: Bump swagger-core.version from 2.2.48 to 2.2.49

Posted by il...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 4_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git

commit 2e2d4ecde5cf7ed960b35a7fd79665b2676355d9
Author: dependabot[bot] <49...@users.noreply.github.com>
AuthorDate: Tue Apr 28 22:35:24 2026 +0000

    Bump swagger-core.version from 2.2.48 to 2.2.49
    
    Bumps `swagger-core.version` from 2.2.48 to 2.2.49.
    
    Updates `io.swagger.core.v3:swagger-annotations-jakarta` from 2.2.48 to 2.2.49
    
    Updates `io.swagger.core.v3:swagger-jaxrs2-jakarta` from 2.2.48 to 2.2.49
    
    ---
    updated-dependencies:
    - dependency-name: io.swagger.core.v3:swagger-annotations-jakarta
      dependency-version: 2.2.49
      dependency-type: direct:production
      update-type: version-update:semver-patch
    - dependency-name: io.swagger.core.v3:swagger-jaxrs2-jakarta
      dependency-version: 2.2.49
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <su...@github.com>
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 7d95d3a264..ba5098ce00 100644
--- a/pom.xml
+++ b/pom.xml
@@ -469,7 +469,7 @@ under the License.
     <cas.version>7.3.6</cas.version>
     <cas-client.version>4.0.4</cas-client.version>
 
-    <swagger-core.version>2.2.48</swagger-core.version>
+    <swagger-core.version>2.2.49</swagger-core.version>
     <swagger-ui.version>5.32.5</swagger-ui.version>
 
     <jquery-slimscroll.version>1.3.8</jquery-slimscroll.version>