diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java
index 6b736bd0c90d6bc08b31689fc8311b3bcd1fcb69..a555d6e885fb2eef149845fc5c06916b48ea094a 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java
@@ -66,6 +66,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.NumberFieldSearchC
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.NumberPropertySearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.PermIdSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.RegistrationDateSearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SamplePropertySearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.StrictlyStringPropertySearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.StringFieldSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.StringPropertySearchCriteria;
@@ -160,6 +161,7 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.L
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.ListableSampleTypeSearchConditionTranslator;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.NameSearchConditionTranslator;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.NumberFieldSearchConditionTranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.SamplePropertySearchConditionTranslator;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.StringFieldSearchConditionTranslator;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.TextAttributeConditionTranslator;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.UserIdSearchConditionTranslator;
@@ -289,7 +291,8 @@ public class CriteriaMapper
                 booleanFieldSearchConditionTranslator);
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(RegistrationDateSearchCriteria.class,
                 dateFieldSearchConditionTranslator);
-//        CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(SamplePropertySearchCriteria.class, );
+        CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(SamplePropertySearchCriteria.class,
+                new SamplePropertySearchConditionTranslator());
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(ShareIdSearchCriteria.class, stringFieldSearchConditionTranslator);
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(SizeSearchCriteria.class, numberFieldSearchConditionTranslator);
         CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(SpeedHintSearchCriteria.class, numberFieldSearchConditionTranslator);
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/AnyPropertySearchConditionTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/AnyPropertySearchConditionTranslator.java
index 7748d194693d763ba4a646f03470449e4ec40117..a58e1bf76857e609e4adacc7d0285775fcc554e0 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/AnyPropertySearchConditionTranslator.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/AnyPropertySearchConditionTranslator.java
@@ -39,7 +39,8 @@ public class AnyPropertySearchConditionTranslator implements IConditionTranslato
         if (criterion.getFieldType() == SearchFieldType.ANY_PROPERTY)
         {
             return TranslatorUtils.getPropertyJoinInformationMap(tableMapper, aliasFactory);
-        } else {
+        } else
+        {
             throw new IllegalArgumentException();
         }
     }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/ControlledVocabularyPropertySearchConditionTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/ControlledVocabularyPropertySearchConditionTranslator.java
index 4bb65920cc92a4ddd2d2f86d8b2a38d7a856677b..d6c8fd32c48816d7c39e2308e167fd8d29e10da0 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/ControlledVocabularyPropertySearchConditionTranslator.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/ControlledVocabularyPropertySearchConditionTranslator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 ETH Zuerich, CISD
+ * Copyright 2023 ETH Zuerich, CISD
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLL
 import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.SELECT;
 import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.SP;
 import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.WHERE;
+import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.CODE_COLUMN;
 import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.ID_COLUMN;
 import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.VOCABULARY_TERM_COLUMN;
 import static ch.systemsx.cisd.openbis.generic.shared.dto.TableNames.CONTROLLED_VOCABULARY_TERM_TABLE;
@@ -53,7 +54,8 @@ public class ControlledVocabularyPropertySearchConditionTranslator
         if (criterion.getFieldType() == SearchFieldType.PROPERTY)
         {
             return TranslatorUtils.getPropertyJoinInformationMap(tableMapper, aliasFactory);
-        } else {
+        } else
+        {
             throw new IllegalArgumentException();
         }
     }
@@ -80,8 +82,7 @@ public class ControlledVocabularyPropertySearchConditionTranslator
         }
     }
 
-    static void doTranslate(final AbstractFieldSearchCriteria<String> criterion,
-            final TableMapper tableMapper,
+    static void doTranslate(final AbstractFieldSearchCriteria<String> criterion, final TableMapper tableMapper,
             final List<Object> args, final StringBuilder sqlBuilder, final Map<String, JoinInformation> aliases)
     {
         final String value = criterion.getFieldValue();
@@ -90,12 +91,12 @@ public class ControlledVocabularyPropertySearchConditionTranslator
         TranslatorUtils.appendPropertiesExist(sqlBuilder, valuesTableAlias);
         sqlBuilder.append(SP).append(AND).append(SP).append(LP);
 
-        appendControlledVocabularyTermIdSubselectConstraint(args, sqlBuilder, value, valuesTableAlias);
+        appendControlledVocabularySubselectConstraint(args, sqlBuilder, value, valuesTableAlias);
 
         sqlBuilder.append(RP);
     }
 
-    private static void appendControlledVocabularyTermIdSubselectConstraint(final List<Object> args,
+    private static void appendControlledVocabularySubselectConstraint(final List<Object> args,
             final StringBuilder sqlBuilder, final String value, final String propertyTableAlias)
     {
         sqlBuilder.append(propertyTableAlias).append(PERIOD).append(VOCABULARY_TERM_COLUMN)
@@ -105,7 +106,7 @@ public class ControlledVocabularyPropertySearchConditionTranslator
         sqlBuilder.append(SELECT).append(SP).append(ID_COLUMN).append(SP)
                 .append(FROM).append(SP).append(CONTROLLED_VOCABULARY_TERM_TABLE).append(SP)
                 .append(WHERE).append(SP);
-        sqlBuilder.append(ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.CODE_COLUMN);
+        sqlBuilder.append(CODE_COLUMN);
 
         sqlBuilder.append(SP).append(EQ).append(SP).append(QU);
         args.add(value);
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/SamplePropertySearchConditionTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/SamplePropertySearchConditionTranslator.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f6183475a03fbb98690c797c6c8b7f9d58f8113
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/SamplePropertySearchConditionTranslator.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2023 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition;
+
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.AND;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.EQ;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.FROM;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.IN;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.LP;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.OR;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.PERIOD;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.QU;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.RP;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.SELECT;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.SP;
+import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.WHERE;
+import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.CODE_COLUMN;
+import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.ID_COLUMN;
+import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.PERM_ID_COLUMN;
+import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.SAMPLE_IDENTIFIER_COLUMN;
+import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.SAMPLE_PROP_COLUMN;
+import static ch.systemsx.cisd.openbis.generic.shared.dto.TableNames.SAMPLES_VIEW;
+
+import java.util.List;
+import java.util.Map;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.AbstractFieldSearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SamplePropertySearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchFieldType;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.utils.JoinInformation;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.utils.TranslatorUtils;
+
+public class SamplePropertySearchConditionTranslator implements IConditionTranslator<SamplePropertySearchCriteria>
+{
+
+    @Override
+    public Map<String, JoinInformation> getJoinInformationMap(final SamplePropertySearchCriteria criterion,
+            final TableMapper tableMapper, final IAliasFactory aliasFactory)
+    {
+        if (criterion.getFieldType() == SearchFieldType.PROPERTY)
+        {
+            return TranslatorUtils.getPropertyJoinInformationMap(tableMapper, aliasFactory);
+        } else
+        {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    @Override
+    public void translate(final SamplePropertySearchCriteria criterion, final TableMapper tableMapper,
+            final List<Object> args, final StringBuilder sqlBuilder, final Map<String, JoinInformation> aliases,
+            final Map<String, String> dataTypeByPropertyCode)
+    {
+        switch (criterion.getFieldType())
+        {
+            case PROPERTY:
+            {
+                doTranslate(criterion, tableMapper, args, sqlBuilder, aliases);
+                break;
+            }
+
+            case ANY_FIELD:
+            case ANY_PROPERTY:
+            case ATTRIBUTE:
+            {
+                throw new IllegalArgumentException("Field type " + criterion.getFieldType() + " is not supported");
+            }
+        }
+    }
+
+    static void doTranslate(final AbstractFieldSearchCriteria<String> criterion, final TableMapper tableMapper,
+            final List<Object> args, final StringBuilder sqlBuilder, final Map<String, JoinInformation> aliases)
+    {
+        final String value = criterion.getFieldValue();
+        final String valuesTableAlias = aliases.get(tableMapper.getValuesTable()).getSubTableAlias();
+
+        TranslatorUtils.appendPropertiesExist(sqlBuilder, valuesTableAlias);
+        sqlBuilder.append(SP).append(AND).append(SP).append(LP);
+
+        if (tableMapper == TableMapper.SAMPLE || tableMapper == TableMapper.EXPERIMENT
+                || tableMapper == TableMapper.DATA_SET)
+        {
+            appendSampleSubselectConstraint(args, sqlBuilder, value, valuesTableAlias);
+        } else
+        {
+            throw new IllegalArgumentException("Sample properties are not supported for " + tableMapper);
+        }
+
+        sqlBuilder.append(RP);
+    }
+
+    private static void appendSampleSubselectConstraint(final List<Object> args, final StringBuilder sqlBuilder,
+            final String value, final String propertyTableAlias)
+    {
+        sqlBuilder.append(propertyTableAlias).append(PERIOD)
+                .append(SAMPLE_PROP_COLUMN).append(SP).append(IN).append(SP);
+        sqlBuilder.append(LP);
+        sqlBuilder.append(SELECT).append(SP).append(ID_COLUMN).append(SP)
+                .append(FROM).append(SP).append(SAMPLES_VIEW).append(SP)
+                .append(WHERE).append(SP);
+
+        translateStringComparison(CODE_COLUMN, value, sqlBuilder, args);
+
+        sqlBuilder.append(SP).append(OR).append(SP);
+        translateStringComparison(PERM_ID_COLUMN, value, sqlBuilder, args);
+
+        sqlBuilder.append(SP).append(OR).append(SP);
+        translateStringComparison(SAMPLE_IDENTIFIER_COLUMN, value, sqlBuilder, args);
+
+        sqlBuilder.append(RP);
+    }
+
+    private static void translateStringComparison(final String columnName, final String value,
+            final StringBuilder sqlBuilder, final List<Object> args)
+    {
+        sqlBuilder.append(columnName).append(SP).append(EQ).append(SP).append(QU);
+        args.add(value);
+    }
+
+}
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractSearchPropertyTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractSearchPropertyTest.java
index e0c24b899e7c86dda39f51a77f66d153381745a5..3ae5dad0fdc972a20be3f5671972febf72b8dcc7 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractSearchPropertyTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractSearchPropertyTest.java
@@ -913,7 +913,7 @@ public abstract class AbstractSearchPropertyTest extends AbstractTest
         assertEquals(entities.size(), 1);
     }
 
-    @Test(enabled = false)
+    @Test
     public void testSearchWithSampleProperty()
     {
         final String sessionToken = v3api.login(TEST_USER, PASSWORD);