diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java index 24834007595..16ce120273e 100644 --- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java +++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java @@ -53,8 +53,6 @@ public final class Constants { public static final String NAME_FIELD_NAME = "name"; - public static final String DEFAULT_TOKEN_FIELD_NAME = "token"; - public static final String ON_CLICK = "click"; public static final String ON_DOUBLE_CLICK = "dblclick"; diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java index b44503fbf96..99014fd3494 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java @@ -350,7 +350,6 @@ protected Model toJSON(final AuditEventTO auditEvent, final Class ref readValue(content, reference); if (entity instanceof UserTO userTO) { userTO.setPassword(null); - userTO.setSecurityAnswer(null); } return Model.of(MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(entity)); diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java index 7f5bedd1c30..ef90b31f0b0 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java @@ -41,7 +41,6 @@ import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BooleanPropertyColumn; import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn; import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn; -import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.TokenColumn; import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal; import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; import org.apache.syncope.client.console.wizards.any.StatusPanel; @@ -222,8 +221,6 @@ protected void addPropertyColumn( if (Constants.KEY_FIELD_NAME.equalsIgnoreCase(name)) { columns.add(new KeyPropertyColumn<>(new ResourceModel(name, name), name, name)); - } else if (Constants.DEFAULT_TOKEN_FIELD_NAME.equalsIgnoreCase(name)) { - columns.add(new TokenColumn<>(new ResourceModel(name, name), name)); } else if (field != null && !field.isSynthetic() && (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class))) { diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/TokenColumn.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/TokenColumn.java deleted file mode 100644 index b7238d968df..00000000000 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/TokenColumn.java +++ /dev/null @@ -1,53 +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.client.console.wicket.extensions.markup.html.repeater.data.table; - -import org.apache.commons.lang3.StringUtils; -import org.apache.syncope.common.lib.to.AnyTO; -import org.apache.syncope.common.lib.to.UserTO; -import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; -import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.repeater.Item; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.ResourceModel; - -public class TokenColumn extends AbstractColumn { - - private static final long serialVersionUID = 8077865338230121496L; - - public TokenColumn(final IModel displayModel, final String sortProperty) { - super(displayModel, sortProperty); - } - - @Override - public void populateItem( - final Item> cellItem, - final String componentId, - final IModel rowModel) { - - if (rowModel.getObject() instanceof final UserTO userTO) { - if (StringUtils.isNotBlank(userTO.getToken())) { - cellItem.add(new Label(componentId, new ResourceModel("tokenValued", "tokenValued"))); - } else { - cellItem.add(new Label(componentId, new ResourceModel("tokenNotValued", "tokenNotValued"))); - } - } - } -} diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserInformationPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserInformationPanel.java index 192a74ec5b8..9d355d2d8a7 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserInformationPanel.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/UserInformationPanel.java @@ -53,21 +53,5 @@ public UserInformationPanel(final String id, final UserTO user // ------------------------ add(new Label("failedLogins", new Model<>(userTO.getFailedLogins()))); // ------------------------ - - // ------------------------ - // Token - // ------------------------ - add(new Label("token", new Model<>(userTO.getToken() == null - ? StringUtils.EMPTY - : userTO.getToken()))); - // ------------------------ - - // ------------------------ - // Token expire time - // ------------------------ - add(new Label("tokenExpireTime", new Model<>(userTO.getTokenExpireTime() == null - ? StringUtils.EMPTY - : SyncopeConsoleSession.get().getDateFormat().format(userTO.getTokenExpireTime())))); - // ------------------------ } } diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/UserInformationPanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/UserInformationPanel.html index 1346f166103..050cd55a11a 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/UserInformationPanel.html +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wizards/any/UserInformationPanel.html @@ -28,10 +28,6 @@
-
-
-
-
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java index 19362b4ce69..567fcb1faf9 100644 --- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java +++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java @@ -26,7 +26,6 @@ import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.lang3.SerializationUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.common.lib.request.AbstractReplacePatchItem; import org.apache.syncope.common.lib.request.AnyObjectUR; @@ -300,13 +299,9 @@ public static UserUR diff(final UserTO updated, final UserTO original, final boo if (updated.getSecurityQuestion() == null) { result.setSecurityQuestion(null); result.setSecurityAnswer(null); - } else if (!updated.getSecurityQuestion().equals(original.getSecurityQuestion()) - || StringUtils.isNotBlank(updated.getSecurityAnswer())) { - + } else if (!updated.getSecurityQuestion().equals(original.getSecurityQuestion())) { result.setSecurityQuestion(new StringReplacePatchItem.Builder(). value(updated.getSecurityQuestion()).build()); - result.setSecurityAnswer( - new StringReplacePatchItem.Builder().value(updated.getSecurityAnswer()).build()); } result.setMustChangePassword(replacePatchItem( diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java index 4567d914dab..cb41968f09c 100644 --- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java +++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java @@ -76,7 +76,6 @@ public static void toAnyCR(final A anyTO, fin userCR.setUsername(userTO.getUsername()); userCR.setPassword(userTO.getPassword()); userCR.setSecurityQuestion(userTO.getSecurityQuestion()); - userCR.setSecurityAnswer(userTO.getSecurityAnswer()); userCR.setMustChangePassword(userTO.isMustChangePassword()); userCR.getMemberships().addAll(userTO.getMemberships()); userCR.getRoles().addAll(userTO.getRoles()); @@ -103,7 +102,6 @@ public static void toAnyTO(final C anyCR, fin userTO.setUsername(userCR.getUsername()); userTO.setPassword(userCR.getPassword()); userTO.setSecurityQuestion(userCR.getSecurityQuestion()); - userTO.setSecurityAnswer(userCR.getSecurityAnswer()); userTO.setMustChangePassword(userCR.isMustChangePassword()); userTO.getMemberships().addAll(userCR.getMemberships()); userTO.getRoles().addAll(userCR.getRoles()); diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java index 8afceec7af5..26998e73f4a 100644 --- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java +++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java @@ -34,14 +34,10 @@ public class UserTO extends AnyTO implements GroupableRelatableTO { private static final long serialVersionUID = 7791304495192615740L; - private String password; - - private String token; - - private OffsetDateTime tokenExpireTime; - private String username; + private String password; + private OffsetDateTime lastLoginDate; private OffsetDateTime changePwdDate; @@ -50,8 +46,6 @@ public class UserTO extends AnyTO implements GroupableRelatableTO { private String securityQuestion; - private String securityAnswer; - private boolean suspended; private boolean mustChangePassword; @@ -84,30 +78,6 @@ public void setType(final String type) { // fixed } - public String getPassword() { - return password; - } - - public void setPassword(final String password) { - this.password = password; - } - - public String getToken() { - return token; - } - - public void setToken(final String token) { - this.token = token; - } - - public OffsetDateTime getTokenExpireTime() { - return tokenExpireTime; - } - - public void setTokenExpireTime(final OffsetDateTime tokenExpireTime) { - this.tokenExpireTime = tokenExpireTime; - } - @JsonProperty(required = true) public String getUsername() { return username; @@ -117,6 +87,14 @@ public void setUsername(final String username) { this.username = username; } + public String getPassword() { + return password; + } + + public void setPassword(final String password) { + this.password = password; + } + public OffsetDateTime getChangePwdDate() { return changePwdDate; } @@ -149,14 +127,6 @@ public void setSecurityQuestion(final String securityQuestion) { this.securityQuestion = securityQuestion; } - public String getSecurityAnswer() { - return securityAnswer; - } - - public void setSecurityAnswer(final String securityAnswer) { - this.securityAnswer = securityAnswer; - } - public boolean isSuspended() { return suspended; } @@ -208,13 +178,10 @@ public int hashCode() { appendSuper(super.hashCode()). append(username). append(roles). - append(token). - append(tokenExpireTime). append(lastLoginDate). append(changePwdDate). append(failedLogins). append(securityQuestion). - append(securityAnswer). append(suspended). append(mustChangePassword). append(memberships). @@ -240,13 +207,10 @@ public boolean equals(final Object obj) { appendSuper(super.equals(obj)). append(username, other.username). append(roles, other.roles). - append(token, other.token). - append(tokenExpireTime, other.tokenExpireTime). append(lastLoginDate, other.lastLoginDate). append(changePwdDate, other.changePwdDate). append(failedLogins, other.failedLogins). append(securityQuestion, other.securityQuestion). - append(securityAnswer, other.securityAnswer). append(suspended, other.suspended). append(mustChangePassword, other.mustChangePassword). append(memberships, other.memberships). diff --git a/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/StandardConfParams.java b/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/StandardConfParams.java index ea58da3bd2c..97ad2ac1af6 100644 --- a/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/StandardConfParams.java +++ b/common/keymaster/client-api/src/main/java/org/apache/syncope/common/keymaster/client/api/StandardConfParams.java @@ -34,8 +34,6 @@ public final class StandardConfParams { public static final String PASSWORD_CIPHER_ALGORITHM = "password.cipher.algorithm"; - public static final String RETURN_PASSWORD_VALUE = "return.password.value"; - public static final String AUTHENTICATION_ATTRIBUTES = "authentication.attributes"; public static final String AUTHENTICATION_STATUSES = "authentication.statuses"; diff --git a/common/keymaster/client-api/src/main/resources/defaultKeymasterConfParams.json b/common/keymaster/client-api/src/main/resources/defaultKeymasterConfParams.json index 7a190abfa42..b74e069f11b 100644 --- a/common/keymaster/client-api/src/main/resources/defaultKeymasterConfParams.json +++ b/common/keymaster/client-api/src/main/resources/defaultKeymasterConfParams.json @@ -9,7 +9,6 @@ "authentication.attributes": ["username"], "authentication.statuses": ["created", "active"], "log.lastlogindate": true, - "return.password.value": false, "jwt.lifetime.minutes": 120, "connector.conf.history.size": 10, "resource.conf.history.size": 10 diff --git a/common/keymaster/client-zookeeper/src/test/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperConfParamOpsITCase.java b/common/keymaster/client-zookeeper/src/test/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperConfParamOpsITCase.java index b1e933f3959..6b1e00a7441 100644 --- a/common/keymaster/client-zookeeper/src/test/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperConfParamOpsITCase.java +++ b/common/keymaster/client-zookeeper/src/test/java/org/apache/syncope/common/keymaster/client/zookeeper/ZookeeperConfParamOpsITCase.java @@ -67,9 +67,10 @@ public void get() { assertNotNull(dateValue); assertEquals(new Date(1554982140000L), dateValue); - Boolean booleanValue = confParamOps.get(DOMAIN, StandardConfParams.RETURN_PASSWORD_VALUE, null, Boolean.class); + Boolean booleanValue = confParamOps.get( + DOMAIN, StandardConfParams.SELF_REGISTRATION_ALLOWED, null, Boolean.class); assertNotNull(booleanValue); - assertEquals(false, booleanValue); + assertEquals(true, booleanValue); List stringValues = List.of(confParamOps.get( DOMAIN, StandardConfParams.AUTHENTICATION_STATUSES, null, String[].class)); diff --git a/common/keymaster/client-zookeeper/src/test/resources/testKeymasterConfParams.json b/common/keymaster/client-zookeeper/src/test/resources/testKeymasterConfParams.json index cee7669fd7f..19baa9ba36b 100644 --- a/common/keymaster/client-zookeeper/src/test/resources/testKeymasterConfParams.json +++ b/common/keymaster/client-zookeeper/src/test/resources/testKeymasterConfParams.json @@ -11,7 +11,6 @@ "authentication.attributes": ["username"], "authentication.statuses": ["created", "active"], "log.lastlogindate": true, - "return.password.value": false, "jwt.lifetime.minutes": 120, "connector.conf.history.size": 10, "resource.conf.history.size": 10, diff --git a/core/persistence-jpa/src/main/resources/domains/MasterKeymasterConfParams.json b/core/persistence-jpa/src/main/resources/domains/MasterKeymasterConfParams.json index 6f2679514ab..c3bfdff7857 100644 --- a/core/persistence-jpa/src/main/resources/domains/MasterKeymasterConfParams.json +++ b/core/persistence-jpa/src/main/resources/domains/MasterKeymasterConfParams.json @@ -11,7 +11,6 @@ "authentication.attributes": ["username"], "authentication.statuses": ["created", "active"], "log.lastlogindate": true, - "return.password.value": false, "jwt.lifetime.minutes": 120, "connector.conf.history.size": 10, "resource.conf.history.size": 10 diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index 59befcd21c9..35b7ca960c5 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -730,7 +730,7 @@ under the License. jobDelegate_id="PullJobDelegate"/> + template='{"_class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"auxClasses":["csv"],"derAttrs":[{"schema":"cn","values":[""]}],"resources":["resource-testdb"],"relationships":[],"memberships":[{"groupKey":"f779c0d4-633b-4be5-8f57-32eb478a3ca5","groupName":null}],"roles":[],"plainAttrs":[{"schema":"ctype","values":["email == 'test8@syncope.apache.org'? 'TYPE_8': 'TYPE_OTHER'"]}]}'/> @@ -750,7 +750,7 @@ under the License. destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="0" syncStatus="1" pullMode="FULL_RECONCILIATION" unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/> + template='{"_class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"auxClasses":[],"derAttrs":[],"resources":[],"relationships":[],"memberships":[],"roles":[],"plainAttrs":[{"schema":"ctype","values":["'type a'"]},{"schema":"userId","values":["'reconciled@syncope.apache.org'"]},{"schema":"fullname","values":["'reconciled fullname'"]},{"schema":"surname","values":["'surname'"]}]}'/> + template='{"_class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":"'/' + title","status":null,"password":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"auxClasses":["minimal group"],"derAttrs":[],"resources":["resource-ldap"],"roles":[],"relationships":[],"memberships":[],"plainAttrs":[]}'/> + template='{"_class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"auxClasses":[],"derAttrs":[],"resources":["resource-testdb"],"roles":[],"relationships":[],"memberships":[],"plainAttrs":[{"schema":"firstname","values":[""]},{"schema":"userId","values":["'test'"]},{"schema":"fullname","values":["'test'"]},{"schema":"surname","values":["'test'"]}]}'/> + template='{"_class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"auxClasses":["csv"],"derAttrs":[{"schema":"cn","values":[""]}],"resources":["resource-testdb"],"relationships":[],"memberships":[{"groupKey":"f779c0d4-633b-4be5-8f57-32eb478a3ca5","groupName":null}],"roles":[],"plainAttrs":[{"schema":"ctype","values":["email == 'test8@syncope.apache.org'? 'TYPE_8': 'TYPE_OTHER'"]}]}'/> + template='{"_class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"auxClasses":[],"derAttrs":[],"resources":[],"relationships":[],"memberships":[],"roles":[],"plainAttrs":[{"schema":"ctype","values":["'type a'"]},{"schema":"userId","values":["'reconciled@syncope.apache.org'"]},{"schema":"fullname","values":["'reconciled fullname'"]},{"schema":"surname","values":["'surname'"]}]}'/> + template='{"_class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":"'/' + title","status":null,"password":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"auxClasses":["minimal group"],"derAttrs":[],"resources":["resource-ldap"],"roles":[],"relationships":[],"memberships":[],"plainAttrs":[]}'/> + template='{"_class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"auxClasses":[],"derAttrs":[],"resources":["resource-testdb"],"roles":[],"relationships":[],"memberships":[],"plainAttrs":[{"schema":"firstname","values":[""]},{"schema":"userId","values":["'test'"]},{"schema":"fullname","values":["'test'"]},{"schema":"surname","values":["'test'"]}]}'/> IGNORE_FIELDS = Set.of( + "class", "serialVersionUID", "cipherAlgorithm", "password", "passwordHistory", + "securityAnswer", "mfa", "token", "tokenExpireTime"); private static final Map, Set>> FIELD_CACHE = Collections.synchronizedMap(new HashMap<>()); @@ -80,7 +81,7 @@ public JexlContextBuilder fields(final Object object) { try { for (PropertyDescriptor desc : Introspector.getBeanInfo(clazz).getPropertyDescriptors()) { if (!desc.getName().startsWith("pc") - && !ArrayUtils.contains(IGNORE_FIELDS, desc.getName()) + && !IGNORE_FIELDS.contains(desc.getName()) && !Collection.class.isAssignableFrom(desc.getPropertyType()) && !Map.class.isAssignableFrom(desc.getPropertyType()) && !desc.getPropertyType().isArray()) { diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java index 5c3abfb116b..b28a72c09f5 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAuditManager.java @@ -50,32 +50,42 @@ public class DefaultAuditManager implements AuditManager { protected static final String MASKED_VALUE = ""; protected static Object maskSensitive(final Object object) { - Object masked; - - if (object instanceof UserTO userTO) { - masked = SerializationUtils.clone(userTO); - if (((UserTO) masked).getPassword() != null) { - ((UserTO) masked).setPassword(MASKED_VALUE); - } - if (((UserTO) masked).getSecurityAnswer() != null) { - ((UserTO) masked).setSecurityAnswer(MASKED_VALUE); + return switch (object) { + case UserTO userTO -> { + UserTO clone = SerializationUtils.clone(userTO); + if (clone.getPassword() != null) { + clone.setPassword(MASKED_VALUE); + } + yield clone; } - } else if (object instanceof UserCR userCR) { - masked = SerializationUtils.clone(userCR); - if (((UserCR) masked).getPassword() != null) { - ((UserCR) masked).setPassword(MASKED_VALUE); + + case UserCR userCR -> { + UserCR clone = SerializationUtils.clone(userCR); + if (clone.getPassword() != null) { + clone.setPassword(MASKED_VALUE); + } + if (clone.getSecurityAnswer() != null) { + clone.setSecurityAnswer(MASKED_VALUE); + } + yield clone; } - if (((UserCR) masked).getSecurityAnswer() != null) { - ((UserCR) masked).setSecurityAnswer(MASKED_VALUE); + + case UserUR userUR -> { + UserUR clone = SerializationUtils.clone(userUR); + if (clone.getPassword() != null) { + clone.getPassword().setValue(MASKED_VALUE); + } + if (clone.getSecurityAnswer() != null) { + clone.getSecurityAnswer().setValue(MASKED_VALUE); + } + yield clone; } - } else if (object instanceof final UserUR userUR && userUR.getPassword() != null) { - masked = SerializationUtils.clone(userUR); - ((UserUR) masked).getPassword().setValue(MASKED_VALUE); - } else { - masked = object; - } - - return masked; + + case null -> + null; + default -> + object; + }; } protected final AuditConfDAO auditConfDAO; diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java index 7b0b5d25951..f576dfa2794 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java @@ -528,11 +528,12 @@ public void setMfa(final String username, final Mfa mfa) { userDAO.save(user); } - protected LinkedAccountTO getLinkedAccountTO(final LinkedAccount account, final boolean returnPasswordValue) { + @Transactional(readOnly = true) + @Override + public LinkedAccountTO getLinkedAccountTO(final LinkedAccount account) { LinkedAccountTO accountTO = new LinkedAccountTO.Builder( account.getKey(), account.getResource().getKey(), account.getConnObjectKeyValue()). username(account.getUsername()). - password(returnPasswordValue ? account.getPassword() : null). suspended(BooleanUtils.isTrue(account.isSuspended())). build(); @@ -542,18 +543,9 @@ protected LinkedAccountTO getLinkedAccountTO(final LinkedAccount account, final return accountTO; } - @Transactional(readOnly = true) - @Override - public LinkedAccountTO getLinkedAccountTO(final LinkedAccount account) { - return getLinkedAccountTO(account, true); - } - @Transactional(readOnly = true) @Override public UserTO getUserTO(final User user, final boolean details) { - Boolean returnPasswordValue = confParamOps.get(AuthContextUtils.getDomain(), - StandardConfParams.RETURN_PASSWORD_VALUE, Boolean.FALSE, Boolean.class); - UserTO userTO = new UserTO(); userTO.setKey(user.getKey()); userTO.setUsername(user.getUsername()); @@ -561,10 +553,6 @@ public UserTO getUserTO(final User user, final boolean details) { userTO.setSuspended(BooleanUtils.isTrue(user.isSuspended())); userTO.setMustChangePassword(user.isMustChangePassword()); - if (returnPasswordValue) { - userTO.setPassword(user.getPassword()); - userTO.setSecurityAnswer(user.getSecurityAnswer()); - } Optional.ofNullable(user.getSecurityQuestion()). map(SecurityQuestion::getKey). ifPresent(userTO::setSecurityQuestion); @@ -580,8 +568,6 @@ public UserTO getUserTO(final User user, final boolean details) { userTO.setChangePwdDate(user.getChangePwdDate()); userTO.setFailedLogins(user.getFailedLogins()); userTO.setLastLoginDate(user.getLastLoginDate()); - userTO.setToken(user.getToken()); - userTO.setTokenExpireTime(user.getTokenExpireTime()); fillTO(user, userTO, derAttrHandler.getValues(user), userDAO.findAllResources(user)); @@ -604,8 +590,8 @@ public UserTO getUserTO(final User user, final boolean details) { membership)).toList()); // linked accounts - userTO.getLinkedAccounts().addAll(user.getLinkedAccounts().stream(). - map(account -> getLinkedAccountTO(account, returnPasswordValue)).toList()); + userTO.getLinkedAccounts().addAll( + user.getLinkedAccounts().stream().map(this::getLinkedAccountTO).toList()); // delegations userTO.getDelegatingDelegations().addAll( diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/CoreReferenceContext.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/CoreReferenceContext.java index 92f30346990..4891b4fe188 100644 --- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/CoreReferenceContext.java +++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/CoreReferenceContext.java @@ -68,4 +68,9 @@ public CustomJWTSSOProvider customJWTSSOProvider( return new CustomJWTSSOProvider(anySearchDAO, authDataAccessor); } + + @Bean + public TestSecurityEndpoint testSecurityEndpoint(final UserDAO userDAO) { + return new TestSecurityEndpoint(userDAO); + } } diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestSecurityEndpoint.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestSecurityEndpoint.java new file mode 100644 index 00000000000..ed2ab18d00f --- /dev/null +++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestSecurityEndpoint.java @@ -0,0 +1,79 @@ +/* + * 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.fit.core.reference; + +import java.util.HashMap; +import java.util.Map; +import org.apache.syncope.core.persistence.api.dao.NotFoundException; +import org.apache.syncope.core.persistence.api.dao.UserDAO; +import org.apache.syncope.core.persistence.api.entity.user.User; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; +import org.springframework.boot.actuate.endpoint.annotation.Selector; +import org.springframework.transaction.annotation.Transactional; + +@Endpoint(id = "testSecurity") +public class TestSecurityEndpoint { + + public enum Element { + PASSWORD, + TOKEN, + FIRST_LINKED_ACCOUNT_PASSWORD; + + } + + private final UserDAO userDAO; + + public TestSecurityEndpoint(final UserDAO userDAO) { + this.userDAO = userDAO; + } + + @ReadOperation + @Transactional(readOnly = true) + public Map get(final @Selector Element element, final @Selector String key) { + User user = userDAO.findById(key).orElseThrow(() -> new NotFoundException("User " + key)); + + return switch (element) { + case PASSWORD -> + user.getPassword() == null + ? Map.of() + : Map.of("password", user.getPassword()); + + case TOKEN -> + user.getToken() == null + ? Map.of() + : Map.of( + "token", user.getToken(), + "tokenExpireTime", user.getTokenExpireTime()); + + case FIRST_LINKED_ACCOUNT_PASSWORD -> { + if (user.getLinkedAccounts().isEmpty()) { + yield Map.of(); + } + + Map result = new HashMap<>(); + result.put("password", user.getLinkedAccounts().getFirst().getPassword()); + yield result; + } + + default -> + Map.of(); + }; + } +} diff --git a/fit/core-reference/src/main/resources/core-embedded.properties b/fit/core-reference/src/main/resources/core-embedded.properties index 42c2f8c1dfa..243f8c42dc3 100644 --- a/fit/core-reference/src/main/resources/core-embedded.properties +++ b/fit/core-reference/src/main/resources/core-embedded.properties @@ -16,7 +16,7 @@ # under the License. embedded.databases=syncope,syncopetwo,syncopetest -management.endpoints.web.exposure.include=health,info,beans,env,loggers,entityCache,job,metrics +management.endpoints.web.exposure.include=health,info,beans,env,loggers,entityCache,job,metrics,testSecurity keymaster.address=http://localhost:9080/syncope/rest/keymaster keymaster.username=${anonymousUser} 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 7b6cf308ff4..6c2888e09d9 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 @@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.json.JsonMapper; import com.nimbusds.jose.JWSAlgorithm; @@ -1135,6 +1136,38 @@ protected static void verifyMail( }); } + protected static String getPassword(final String key) throws JsonProcessingException { + String response = WebClient.create( + StringUtils.substringBeforeLast(ADDRESS, "/") + "/actuator/testSecurity/PASSWORD/" + key, + ANONYMOUS_UNAME, + ANONYMOUS_KEY, + null). + accept(MediaType.APPLICATION_JSON).get().readEntity(String.class); + @SuppressWarnings("unchecked") + Map payload = MAPPER.readValue(response, Map.class); + return payload.isEmpty() + ? null + : Optional.ofNullable(payload.get("password")).map(Object::toString).orElse(null); + } + + protected static Map getToken(final String key) { + String response = WebClient.create( + StringUtils.substringBeforeLast(ADDRESS, "/") + "/actuator/testSecurity/TOKEN/" + key, + ANONYMOUS_UNAME, + ANONYMOUS_KEY, + null). + accept(MediaType.APPLICATION_JSON).get().readEntity(String.class); + + try { + @SuppressWarnings("unchecked") + Map payload = MAPPER.readValue(response, Map.class); + return payload; + } catch (Exception e) { + LOG.error("Could not parse {}", response, e); + return Map.of(); + } + } + @Autowired protected ConfParamOps confParamOps; diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/KeymasterITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/KeymasterITCase.java index acad69e0bb9..d4ec3054f20 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/KeymasterITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/KeymasterITCase.java @@ -80,9 +80,9 @@ public void confParamGet() { assertEquals(120L, longValue.longValue()); Boolean booleanValue = confParamOps.get( - SyncopeConstants.MASTER_DOMAIN, StandardConfParams.RETURN_PASSWORD_VALUE, null, Boolean.class); + SyncopeConstants.MASTER_DOMAIN, StandardConfParams.PASSWORD_RESET_ALLOWED, null, Boolean.class); assertNotNull(booleanValue); - assertEquals(false, booleanValue); + assertEquals(true, booleanValue); List stringValues = List.of(confParamOps.get( SyncopeConstants.MASTER_DOMAIN, StandardConfParams.AUTHENTICATION_ATTRIBUTES, null, String[].class)); diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java index a522f0c98c4..27b1f93dc04 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java @@ -28,11 +28,13 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeFalse; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.node.ObjectNode; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.UUID; import org.apache.commons.lang3.RandomStringUtils; @@ -81,6 +83,21 @@ public class LinkedAccountITCase extends AbstractITCase { + protected static String getFirstLinkedAccountPassword(final String key) throws JsonProcessingException { + String response = WebClient.create( + StringUtils.substringBeforeLast(ADDRESS, "/") + + "/actuator/testSecurity/FIRST_LINKED_ACCOUNT_PASSWORD/" + key, + ANONYMOUS_UNAME, + ANONYMOUS_KEY, + null). + accept(MediaType.APPLICATION_JSON).get().readEntity(String.class); + @SuppressWarnings("unchecked") + Map payload = MAPPER.readValue(response, Map.class); + return payload.isEmpty() + ? null + : Optional.ofNullable(payload.get("password")).map(Object::toString).orElse(null); + } + @Test public void createWithLinkedAccountThenUpdateThenRemove() { // 1. create user with linked account @@ -209,11 +226,8 @@ public void createWithoutLinkedAccountThenAdd() { } @Test - public void createWithoutLinkedAccountThenAddAndUpdatePassword() { - // 1. set the return value parameter to true - confParamOps.set(SyncopeConstants.MASTER_DOMAIN, StandardConfParams.RETURN_PASSWORD_VALUE, true); - - // 2. create user without linked account + public void createWithoutLinkedAccountThenAddAndUpdatePassword() throws JsonProcessingException { + // 1. create user without linked account UserCR userCR = UserITCase.getSample( "linkedAccount" + RandomStringUtils.insecure().nextNumeric(5) + "@syncope.apache.org"); String connObjectKeyValue = "uid=" + userCR.getUsername() + ",ou=People,o=isp"; @@ -222,7 +236,7 @@ public void createWithoutLinkedAccountThenAddAndUpdatePassword() { assertNotNull(user.getKey()); assertTrue(user.getLinkedAccounts().isEmpty()); - // 3. add linked account to user without password + // 2. add linked account to user without password UserUR userUR = new UserUR(); userUR.setKey(user.getKey()); @@ -231,15 +245,15 @@ public void createWithoutLinkedAccountThenAddAndUpdatePassword() { user = updateUser(userUR).getEntity(); assertEquals(1, user.getLinkedAccounts().size()); - assertNull(user.getLinkedAccounts().getFirst().getPassword()); + assertNull(getFirstLinkedAccountPassword(user.getKey())); - // 4. update linked account with adding a password + // 3. update linked account with adding a password account.setPassword("Password123"); userUR = new UserUR(); userUR.setKey(user.getKey()); userUR.getLinkedAccounts().add(new LinkedAccountUR.Builder().linkedAccountTO(account).build()); - // 4.1 SYNCOPE-1824 update with a wrong password, a error must be raised + // 3.1 SYNCOPE-1824 update with a wrong password, a error must be raised account.setPassword("password"); try { updateUser(userUR); @@ -258,7 +272,7 @@ public void createWithoutLinkedAccountThenAddAndUpdatePassword() { // set a correct password account.setPassword("Password123"); user = updateUser(userUR).getEntity(); - assertNotNull(user.getLinkedAccounts().getFirst().getPassword()); + assertNotNull(getFirstLinkedAccountPassword(user.getKey())); PagedResult tasks = TASK_SERVICE.search( new TaskQuery.Builder(TaskType.PROPAGATION).resource(RESOURCE_NAME_LDAP). @@ -271,8 +285,8 @@ public void createWithoutLinkedAccountThenAddAndUpdatePassword() { assertTrue(propagationData.getAttributes().stream(). anyMatch(a -> OperationalAttributes.PASSWORD_NAME.equals(a.getName()))); - // 5. update linked account password - String beforeUpdatePassword = user.getLinkedAccounts().getFirst().getPassword(); + // 4. update linked account password + String beforeUpdatePassword = getFirstLinkedAccountPassword(user.getKey()); account.setPassword("Password123Updated"); userUR = new UserUR(); userUR.setKey(user.getKey()); @@ -284,8 +298,8 @@ public void createWithoutLinkedAccountThenAddAndUpdatePassword() { userUR.getLinkedAccounts().add(new LinkedAccountUR.Builder().linkedAccountTO(account).build()); user = updateUser(userUR).getEntity(); - assertNotNull(user.getLinkedAccounts().getFirst().getPassword()); - assertNotEquals(beforeUpdatePassword, user.getLinkedAccounts().getFirst().getPassword()); + assertNotNull(getFirstLinkedAccountPassword(user.getKey())); + assertNotEquals(beforeUpdatePassword, getFirstLinkedAccountPassword(user.getKey())); tasks = TASK_SERVICE.search( new TaskQuery.Builder(TaskType.PROPAGATION).resource(RESOURCE_NAME_LDAP). @@ -298,16 +312,14 @@ public void createWithoutLinkedAccountThenAddAndUpdatePassword() { assertTrue(propagationData.getAttributes().stream(). anyMatch(a -> OperationalAttributes.PASSWORD_NAME.equals(a.getName()))); - // 6. set linked account password to null + // 5. set linked account password to null account.setPassword(null); userUR = new UserUR(); userUR.setKey(user.getKey()); userUR.getLinkedAccounts().add(new LinkedAccountUR.Builder().linkedAccountTO(account).build()); user = updateUser(userUR).getEntity(); - assertNull(user.getLinkedAccounts().getFirst().getPassword()); - - confParamOps.set(SyncopeConstants.MASTER_DOMAIN, StandardConfParams.RETURN_PASSWORD_VALUE, false); + assertNull(getFirstLinkedAccountPassword(user.getKey())); } @Test 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 2cafee9305b..22e0d0b0564 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 @@ -29,6 +29,7 @@ import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; +import com.fasterxml.jackson.core.JsonProcessingException; import jakarta.ws.rs.NotAuthorizedException; import jakarta.ws.rs.core.GenericType; import jakarta.ws.rs.core.Response; @@ -39,6 +40,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.function.Function; @@ -495,13 +497,12 @@ public void list() { } @Test - public void read() { + public void read() throws JsonProcessingException { UserTO userTO = USER_SERVICE.read("1417acbe-cbf6-4277-9372-e75e04f97000"); - assertNotNull(userTO); - assertNull(userTO.getPassword()); assertNotNull(userTO.getPlainAttrs()); assertFalse(userTO.getPlainAttrs().isEmpty()); + assertNotNull(getPassword(userTO.getKey())); } @Test @@ -730,42 +731,42 @@ public void createActivate() { assumeTrue(IS_FLOWABLE_ENABLED); UserCR userCR = getUniqueSample("createActivate@syncope.apache.org"); - userCR.getMemberships().add(new MembershipTO.Builder("268fed79-f440-4390-9435-b273768eb5d6").build()); UserTO userTO = createUser(userCR).getEntity(); - assertNotNull(userTO); - assertNotNull(userTO.getToken()); - assertNotNull(userTO.getTokenExpireTime()); - assertEquals("created", userTO.getStatus()); - StatusR statusR = new StatusR.Builder(userTO.getKey(), StatusRType.ACTIVATE).token(userTO.getToken()).build(); + Map map = getToken(userTO.getKey()); + assertNotNull(map.get("token")); + assertNotNull(map.get("tokenExpireTime")); + + StatusR statusR = new StatusR.Builder(userTO.getKey(), StatusRType.ACTIVATE). + token(map.get("token").toString()).build(); userTO = USER_SERVICE.status(statusR).readEntity(new GenericType>() { }).getEntity(); - assertNotNull(userTO); - assertNull(userTO.getToken()); - assertNull(userTO.getTokenExpireTime()); assertEquals("active", userTO.getStatus()); + + map = getToken(userTO.getKey()); + assertNull(map.get("token")); + assertNull(map.get("tokenExpireTime")); } @Test public void suspendReactivate() { UserCR userCR = getUniqueSample("suspendReactivate@syncope.apache.org"); - userCR.getMemberships().add(new MembershipTO.Builder("bf825fe1-7320-4a54-bd64-143b5c18ab97").build()); UserTO userTO = createUser(userCR).getEntity(); - assertNotNull(userTO); assertEquals(IS_FLOWABLE_ENABLED ? "active" : "created", userTO.getStatus()); - StatusR statusR = new StatusR.Builder(userTO.getKey(), StatusRType.SUSPEND).token(userTO.getToken()).build(); + String token = Optional.ofNullable(getToken(userTO.getKey()).get("token")).map(Object::toString).orElse(null); + StatusR statusR = new StatusR.Builder(userTO.getKey(), StatusRType.SUSPEND).token(token).build(); userTO = USER_SERVICE.status(statusR).readEntity(new GenericType>() { }).getEntity(); diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java index 72648cbe570..9da21a897c5 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java @@ -28,6 +28,7 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeFalse; +import com.fasterxml.jackson.core.JsonProcessingException; import jakarta.ws.rs.HttpMethod; import jakarta.ws.rs.core.GenericType; import jakarta.ws.rs.core.MediaType; @@ -458,7 +459,7 @@ public void issueSYNCOPE279() { } @Test - public void issueSYNCOPE122() { + public void issueSYNCOPE122() throws JsonProcessingException { // 1. create user on testdb and testdb2 UserCR userCR = UserITCase.getUniqueSample("syncope122@apache.org"); userCR.getResources().clear(); @@ -471,7 +472,7 @@ public void issueSYNCOPE122() { assertTrue(userTO.getResources().contains(RESOURCE_NAME_TESTDB)); assertTrue(userTO.getResources().contains(RESOURCE_NAME_TESTDB2)); - String pwdOnSyncope = userTO.getPassword(); + String pwdOnSyncope = getPassword(userTO.getKey()); ConnObject userOnDb = RESOURCE_SERVICE.readConnObject( RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userTO.getKey()); @@ -504,7 +505,7 @@ public void issueSYNCOPE122() { assertEquals(RESOURCE_NAME_TESTDB, result.getPropagationStatuses().getFirst().getResource()); // 3b. verify that password hasn't changed on Syncope - assertEquals(pwdOnSyncope, userTO.getPassword()); + assertEquals(pwdOnSyncope, getPassword(userTO.getKey())); // 3c. verify that password *has* changed on testdb userOnDb = RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userTO.getKey()); @@ -1072,7 +1073,7 @@ public void issueSYNCOPE505LDAP() throws Exception { } @Test - public void issueSYNCOPE391() { + public void issueSYNCOPE391() throws JsonProcessingException { assumeFalse(IS_EXT_SEARCH_ENABLED); // 1. create user on Syncope with null password @@ -1082,7 +1083,7 @@ public void issueSYNCOPE391() { UserTO userTO = createUser(userCR).getEntity(); assertNotNull(userTO); - assertNull(userTO.getPassword()); + assertNull(getPassword(userTO.getKey())); // 2. create existing user on csv and check that password on Syncope is null and that password on resource // doesn't change @@ -1110,7 +1111,7 @@ public void issueSYNCOPE391() { assertEquals( "password0", connObjectTO.getAttr(OperationalAttributes.PASSWORD_NAME).orElseThrow().getValues().getFirst()); - assertNull(userTO.getPassword()); + assertNull(getPassword(userTO.getKey())); // 3. create user with not null password and propagate onto resource-csv, specify not to save password on // Syncope local storage @@ -1127,11 +1128,11 @@ public void issueSYNCOPE391() { RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), userTO.getKey()); assertNotNull(connObjectTO); - // check if password has been propagated and that saved userTO's password is null + // check if password has been propagated and that saved user's password is null assertEquals( "passwordTESTNULL1", connObjectTO.getAttr(OperationalAttributes.PASSWORD_NAME).orElseThrow().getValues().getFirst()); - assertNull(userTO.getPassword()); + assertNull(getPassword(userTO.getKey())); // 4. create user and propagate password on resource-csv and on Syncope local storage userCR = UserITCase.getUniqueSample("syncope391@syncope.apache.org"); diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java index 37ce4f23573..fe24ac5a48f 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java @@ -33,6 +33,7 @@ import jakarta.ws.rs.core.GenericType; import jakarta.ws.rs.core.Response; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -369,7 +370,7 @@ public void passwordReset() throws Exception { } String token = await().atMost(MAX_WAIT_SECONDS, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until( - () -> USER_SERVICE.read(read.getKey()).getToken(), + () -> Optional.ofNullable(getToken(read.getKey()).get("token")).map(Object::toString).orElse(null), StringUtils::isNotBlank); // 5. confirm password reset @@ -387,8 +388,8 @@ public void passwordReset() throws Exception { } // 6. verify that password was reset and token removed - authClient = CLIENT_FACTORY.create(user.getUsername(), "newPassword123"); - assertNull(authClient.self().user().getToken()); + CLIENT_FACTORY.create(user.getUsername(), "newPassword123"); + assertNull(Optional.ofNullable(getToken(read.getKey()).get("token")).map(Object::toString).orElse(null)); // 7. verify that password was changed on external resource String newPwdOnResource = queryForObject(jdbcTemplate, @@ -415,7 +416,7 @@ public void passwordResetWithoutSecurityQuestion() { ANONYMOUS_CLIENT.getService(UserSelfService.class).requestPasswordReset(user.getUsername(), null); // 4. get token (normally sent via e-mail, now reading as admin) - String token = USER_SERVICE.read(read.getKey()).getToken(); + String token = Optional.ofNullable(getToken(read.getKey()).get("token")).map(Object::toString).orElse(null); assertNotNull(token); // 5. confirm password reset @@ -429,10 +430,8 @@ public void passwordResetWithoutSecurityQuestion() { ANONYMOUS_CLIENT.getService(UserSelfService.class).confirmPasswordReset(token, "newPassword123"); // 6. verify that password was reset and token removed - authClient = CLIENT_FACTORY.create(user.getUsername(), "newPassword123"); - read = authClient.self().user(); - assertNotNull(read); - assertNull(read.getToken()); + CLIENT_FACTORY.create(user.getUsername(), "newPassword123"); + assertNull(Optional.ofNullable(getToken(read.getKey()).get("token")).map(Object::toString).orElse(null)); // 7. re-enable security question for password reset confParamOps.set(SyncopeConstants.MASTER_DOMAIN, StandardConfParams.PASSWORD_RESET_SECURITY_QUESTION, true); diff --git a/pom.xml b/pom.xml index 8d1295779e3..218a219c15f 100644 --- a/pom.xml +++ b/pom.xml @@ -529,7 +529,7 @@ under the License. 10.1.54 39.0.1.Final 6.2025.11 - 4.1.7 + 4.1.8 18-alpine 9.0 diff --git a/src/main/asciidoc/reference-guide/configuration/configurationparameters.adoc b/src/main/asciidoc/reference-guide/configuration/configurationparameters.adoc index 51fc6f06bb1..e55ba970f4e 100644 --- a/src/main/asciidoc/reference-guide/configuration/configurationparameters.adoc +++ b/src/main/asciidoc/reference-guide/configuration/configurationparameters.adoc @@ -61,7 +61,6 @@ mechanism to work properly; [WARNING] Suspended Users are anyway not allowed to authenticate. * `log.lastlogindate` - whether the system updates the `lastLoginDate` field of users upon authentication; -* `return.password.value` - whether the hashed password value and the hashed security answer (if any) value shall be * `connector.test.timeout` - timeout (in seconds) to check connector connection in <>; `0` to skip any check;