diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@
 `ldap-scim-bridge` uses [PVP][1]-compatible versioning.
 The changelog is available [on GitHub][2].
 
+## 0.4
+
+- Filter for arbitrary LDAP attributes (#16)
+
 ## 0.3
 
 - Better error logging. (#11)
diff --git a/examples/wire-server/conf1.yaml b/examples/wire-server/conf1.yaml
--- a/examples/wire-server/conf1.yaml
+++ b/examples/wire-server/conf1.yaml
@@ -8,6 +8,8 @@
   search:
     base: "ou=People,dc=nodomain"
     objectClass: "account"
+    #memberOf: "team red"
+    #hairColor: "yellow"
   codec: "utf8"
 scimTarget:
   tls: false
diff --git a/ldap-scim-bridge.cabal b/ldap-scim-bridge.cabal
--- a/ldap-scim-bridge.cabal
+++ b/ldap-scim-bridge.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.4
 name:                ldap-scim-bridge
-version:             0.3
+version:             0.4
 synopsis:            See README for synopsis
 description:         See README for description
 homepage:            https://github.com/fisx/ldap-scim-bridge
@@ -39,6 +39,7 @@
                      , email-validate >=2.3.2.13 && <2.4
                      , string-conversions >=0.4.0.1 && <0.5
                      , servant-client >=0.18.3 && <0.19
+                     , unordered-containers >= 0.2.14.0 && <0.3
                      , servant-client-core >=0.18.3 && <0.19
                      , servant >=0.18.3 && <0.19
                      , http-types >=0.12.3 && <0.13
diff --git a/src/LdapScimBridge.hs b/src/LdapScimBridge.hs
--- a/src/LdapScimBridge.hs
+++ b/src/LdapScimBridge.hs
@@ -8,6 +8,7 @@
 import qualified Data.Aeson.Encode.Pretty as Aeson
 import qualified Data.ByteString.Char8 as ByteString
 import qualified Data.Foldable as Foldable
+import qualified Data.HashMap.Lazy as HM
 import qualified Data.List
 import qualified Data.Map as Map
 import Data.String.Conversions (cs)
@@ -63,7 +64,9 @@
   { -- | `$ slapcat | grep ^dn`, eg. @Dn "dc=nodomain"@.
     ldapSearchBase :: Dn,
     -- | eg. @"account"@
-    ldapSearchObjectClass :: Text
+    ldapSearchObjectClass :: Text,
+    -- | eg. @[LdapFilterAttr "memberOf" "team red", LdapFilterAttr "hairColor" "yellow"]
+    ldapSearchExtra :: [LdapFilterAttr]
   }
   deriving stock (Eq, Show)
 
@@ -79,7 +82,7 @@
     fpassword :: String <- obj Aeson..: "password"
     fsearch :: LdapSearch <- obj Aeson..: "search"
     fcodec :: Text <- obj Aeson..: "codec"
-    fdeleteOnAttribute :: Maybe LdapFilterAttr <- obj Aeson..:? "deleteOnAttribute"
+    fdeleteOnAttribute :: Maybe LdapFilterAttr <- obj Aeson..:? "deleteOnAttribute" -- TODO: this can go into 'fdeleteFromDirectory'.
     fdeleteFromDirectory :: Maybe LdapSearch <- obj Aeson..:? "deleteFromDirectory"
 
     let vhost :: Host
@@ -117,8 +120,15 @@
   parseJSON = Aeson.withObject "LdapSearch" $ \obj -> do
     fbase :: Text <- obj Aeson..: "base"
     fobjectClass :: Text <- obj Aeson..: "objectClass"
-    pure $ LdapSearch (Dn fbase) fobjectClass
 
+    extra :: [LdapFilterAttr] <- do
+      let go :: (Text, Yaml.Value) -> Yaml.Parser LdapFilterAttr
+          go (key, val) = do
+            str <- Aeson.withText "val" pure val
+            pure $ LdapFilterAttr key str
+      go `mapM` HM.toList (HM.filterWithKey (\k _ -> k `notElem` ["base", "objectClass"]) obj)
+    pure $ LdapSearch (Dn fbase) fobjectClass extra
+
 data ScimConf = ScimConf
   { scimTls :: Bool,
     scimHost :: String,
@@ -143,7 +153,7 @@
     mapping :: Mapping,
     logLevel :: Level
   }
-  deriving stock (Generic)
+  deriving stock (Show, Generic)
 
 instance Aeson.FromJSON Level where
   parseJSON "Trace" = pure Trace
@@ -255,14 +265,18 @@
 
 type LdapResult a = IO (Either LdapError a)
 
-ldapObjectClassFilter :: Text -> Filter
+ldapObjectClassFilter :: Text -> Filter -- TODO: inline?
 ldapObjectClassFilter = (Attr "objectClass" :=) . cs
 
+ldapFilterAttrToFilter :: LdapFilterAttr -> Filter -- TODO: inline?  replace LdapFilterAttr with `Attr` and `:=`?
+ldapFilterAttrToFilter (LdapFilterAttr key val) = Attr key := (cs val)
+
 listLdapUsers :: LdapConf -> LdapSearch -> LdapResult [SearchEntry]
 listLdapUsers conf searchConf = Ldap.with (ldapHost conf) (ldapPort conf) $ \l -> do
   Ldap.bind l (ldapDn conf) (ldapPassword conf)
-  let fltr = ldapObjectClassFilter . ldapSearchObjectClass $ searchConf
-  Ldap.search l (ldapSearchBase searchConf) mempty fltr mempty
+  let fltr :: Filter = ldapObjectClassFilter . ldapSearchObjectClass $ searchConf
+      allfltr :: Filter = And (fltr :| (ldapFilterAttrToFilter <$> ldapSearchExtra searchConf))
+  Ldap.search l (ldapSearchBase searchConf) mempty allfltr mempty
 
 type User = Scim.User ScimTag
 
