User directory: Local user filter for MS Graph

To circumvent certain limitations of the MS Graph API, we introduced the local user filter.

These limitations currently include filtering users by their group memberships in case those filter groups are not part of the synchronized groups. While such a requirement can easily be done with an LDAP expression, the same is not possible with an MS Graph query.


The local user filter acts just like the normal user filter and contains an OData filter expression.

The difference is that it is not part of the query to the MS Graph API but will be executed on the Haiilo backend on the response that was received. This effectively creates a two-stage user filter.

The goal is to minimize the MS Graph response size by filtering as much as you can in the 1st stage 'user filter' and then use expressions in the 2nd stage 'local user filter' that MS Graph does not support.

The syntax and grammar are that of OData filter expressions, just like the regular MS Graph user filter, so you don't have to learn a new concept.

All used property names in the local user filter expression need to be selected in the query so that they appear in the MS Graph response. This is done automatically as well as the distinction between selectable and expandable properties. However, there are limitations of the MS Graph API that can be reached quickly. For instance, only one expandable property is allowed in a query.

If you filter for the 'memberOf' in the local user filter and use 'extensions' in the profile field mapping or sync the manager field, then the limit has already been exceeded.

Supported OData expressions

  • Equality operators
    • Equals (eq)
    • Not equals (ne)
    • Logical negation (not)
    • In (in)
  • Relational operators
    • Less than (th)
    • Greater than (gt)
    • Less than or equal to (le)
    • Greater than or equal to (ge)
  • Lambda operators
    • Any (any)
    • All (all)
    • Conditional operators
    • And (and)
    • Or (or)
  • Functions
    • Starts with (startsWith)
    • Ends with (endsWith)
    • Contains (contains)
  • Parentheses for grouping of operators
  • Data types:
    • null¬†
    • strings
    • integers
    • booleans
    • GUID

Compare with official Microsoft documentation for filters.

Simplifying OData expressions

The following rules help to simplify expression that make use of the 'any', 'all' and 'in' operators using boolean algebra:

x/any(p:expr1) or x/any(p:expr2) = x/any(p:expr1 or expr2)
x/any(p:expr1) and x/any(p:expr2) : can not be simplified
x/all(p:expr1) and x/all(p:expr2) = x/all(p:expr1 and expr2)
x/all(p:expr1) or x/all(p:expr2) : can not be simplified
(x eq a) or (x eq b) = x in (a, b)


You have a group with the name 'A' and another named 'B', and you want to synchronize users that are members of both groups, but you don't want to synchronize all users of 'A' and 'B' at the same time.

A user filter expression that satisfies those requirements would be:

memberOf/any(m:m/displayName eq 'A') and memberOf/any(m:m/displayName eq 'B')

You want to select only those users whose manager's office location is "London". Surprisingly this filter is just ignored by the MS Graph API, but with a local filter expression, you are able to do it:

manager/city eq 'London'


MS Graph

  • No more than 2 expandable properties allowed.

Local OData syntax and grammar

  • Expandable collections: only 'memberOf' is currently allowed
  • The property names are case-sensitive. Use 'memberOf' and not 'memberof'
  • Comparing collections and complex objects is not supported
  • Unsupported grammar:
    • data types: date, time, duration, decimal, geography, geometry
    • OData 4 functions: length, indexof, substring, tolower, toupper, trim, concat
    • 'has' operator
    • namespaces
    • compound keys
    • bound functions
    • qualified entities
    • enum types

Was this article helpful?