Browse docs

LDAP filters

Learn how LDAP search filters work and how to construct them safely, from RFC 4515 syntax to common patterns.

On this page

A filter is a boolean expression that decides which entries a search matches. Filters are written in a fully-parenthesized prefix syntax defined by RFC 4515, which looks unusual at first but is simple once you've seen a few examples.

Basic equality

The simplest filter checks whether an attribute equals a value:

(cn=Jane Doe)
  • cn equals Jane Doe

Every filter is wrapped in parentheses. attribute=value inside those parentheses is an equality match.

Combining filters with AND / OR / NOT

Filters combine using prefix operators — the operator comes before its operands, and every operand is itself a fully parenthesized filter:

(&(objectClass=user)(mail=*@example.com))
  • AND
    • objectClass equals user
    • mail matches *@example.com
  • & means AND — every child filter must match.
  • | means OR — at least one child filter must match.
  • ! means NOT — negates a single child filter.
(|(department=Engineering)(department=Product))
  • OR
    • department equals Engineering
    • department equals Product
(!(accountDisabled=TRUE))
  • NOT
    • accountDisabled equals TRUE
Wildcards and substrings

* matches any run of characters, so you can match prefixes, suffixes, or "contains" checks:

(mail=*@example.com)
  • mail matches *@example.com
(cn=Jane*)
  • cn matches Jane*

A bare * by itself as the value means "has any value at all" — a presence filter:

(mail=*)
  • mail is present

This is a common way to check "does this entry have this attribute set," regardless of what it's set to.

Comparison operators

Besides equality, LDAP filters support ordering comparisons on attributes that have an ordering matching rule (most commonly integers and generalized time):

(&(objectClass=user)(createTimestamp>=20240101000000Z))
  • AND
    • objectClass equals user
    • createTimestamp20240101000000Z

>= and <= are supported; there is no strict > or < in the LDAP filter grammar.

Escaping values

Because * ( ) \ and the null character are meaningful in filter syntax, any value that might contain them needs to be escaped before it's inserted into a filter string — * becomes \2a, ( becomes \28, and so on. This matters most when a value comes from user input:

Security

Never interpolate untrusted input directly into an LDAP filter string. An unescaped *, (, or ) can change what the filter matches entirely — the same class of bug as SQL injection. See LDAP injection for concrete examples, and always escape with a library function rather than by hand.

Build filters interactively

Rather than hand-writing nested parentheses, construct and validate filters visually, including correct escaping of any values you type in.

What's next

Filters determine which entries you find. The next pages cover a specific kind of entry you'll filter for constantly: Users and groups.