LdapDataProvider
The LdapDataProvider loads the data of an Object or ObjectCollection directly from an LDAP or LDAPS directory — for example from an Active Directory. This makes it possible to pick people, groups or location data from the directory inside a form, without exporting them to a database or file first.
The provider is a service-based data provider: the query runs server-side via the DataService, just like the SqlDataProvider and HttpDataProvider.
Configuration
In addition to Mapping or Code and the optional SearchParameters (see Data interface), the LdapDataProvider is configured through the Options element:
<LdapDataProvider DisplayName="Employees">
<SearchParameters>
<Text Id="lastName" Label="Last name" />
</SearchParameters>
<Options>
<Server>ldaps://dc01.example.com</Server>
<UserName>CN=Service,OU=Accounts,DC=example,DC=com</UserName>
<Password>{EncryptedPassword}</Password>
<BaseDn>OU=Users,DC=example,DC=com</BaseDn>
<Filter>(&(objectClass=user)(sn={lastName}*))</Filter>
<Attributes>cn,sn,givenName,mail,telephoneNumber</Attributes>
</Options>
<Mapping>
<Map Source="givenName" Target="FirstName" />
<Map Source="sn" Target="LastName" />
<Map Source="mail" Target="Email" />
</Mapping>
</LdapDataProvider>
Options
| Element | Description |
|---|---|
Server (optional) | LDAP server. Accepted are a plain host name, host:port, ldap://host[:port] (default port 389) or ldaps://host[:port] (SSL/TLS, default port 636). IPv6 literals are supported — unbracketed without a port (fe80::1), bracketed with a port ([2001:db8::1]:636). If omitted, the current computer's domain is used over plain LDAP on port 389; ldaps:// requires an explicit server. |
UserName (optional) | Distinguished name or user principal name for the simple bind, e.g. CN=Service,OU=Accounts,DC=example,DC=com or service@example.com. Only valid together with Password, see Authentication. |
Password (optional) | Password for the simple bind. It is encrypted the same way as the ConnectionString of the SqlDataProvider (see Encryption). Only valid together with UserName. |
BaseDn (optional) | Distinguished name of the search base, e.g. OU=Users,DC=example,DC=com. If omitted, the defaultNamingContext is read from the server's RootDSE. |
Filter (required) | LDAP search filter per RFC 4515, e.g. (&(objectClass=user)(sn={lastName}*)). {placeholder} tokens are replaced with the values of the SearchParameters (see Placeholders in the filter). |
Attributes (optional) | Comma-separated list of attributes to return, e.g. cn,sn,givenName,mail. If omitted, all user attributes are returned (no operational attributes). |
Scope (optional) | Search depth relative to the BaseDn: Base (the base entry only), OneLevel (direct children only) or Subtree (the entire subtree, default). |
SizeLimit (optional) | Maximum number of entries returned. 0 (default) leaves the limit to the server. |
IgnoreCertificateErrors (optional) | If true: certificate errors are ignored for ldaps:// connections (e.g. self-signed certificates). Default false — certificate validation is therefore active. |
Authentication and automatic discovery
When the primedocs server runs in the same Active Directory domain as the directory, the Filter alone is enough — server, credentials and search base are determined at runtime. This mirrors the behaviour of the LdapSyncSource in user sync.
- With credentials:
UserNameandPasswordonly take effect as a pair. If just one of them is set, configuration validation reports an error and the query fails at runtime. The connection uses a simple bind. - Without credentials: if both are omitted, the provider authenticates as the account the server process runs under (Windows authentication,
Negotiate). No service account has to be configured.
Minimal configuration for this scenario:
<LdapDataProvider DisplayName="Employees">
<Options>
<Filter>(&(objectClass=user)(objectCategory=person))</Filter>
</Options>
<Mapping>
<Map Source="givenName" Target="FirstName" />
<Map Source="sn" Target="LastName" />
<Map Source="mail" Target="Email" />
</Mapping>
</LdapDataProvider>
When automatic discovery fails
| Situation | Behaviour |
|---|---|
Server is omitted and the computer's domain cannot be determined (machine not domain-joined, non-Windows platform, missing permission) | The query aborts with a hint to configure <Server> explicitly. |
BaseDn is omitted and the server's RootDSE provides no defaultNamingContext | The query aborts with a hint to configure <BaseDn> explicitly. |
Only UserName or only Password is set | Configuration error: "UserName and Password must be configured together — omit both to authenticate as the current process account (Negotiate)." |
Placeholders in the filter
In the Filter, {placeholder} tokens are replaced with the value of the search parameter of the same name. In the example above, the lastName search parameter fills the {lastName} placeholder.
The inserted values are escaped according to RFC 4515. User input therefore cannot alter the filter structure (protection against LDAP injection) — characters such as *, (, ) or \ are treated as literals and do not act as filter operators.
Because input is escaped, an asterisk typed by the user does not act as a wildcard. To allow a "starts with" search, put the asterisk into the filter itself: (sn={lastName}*).
Result and mapping
Every directory entry found becomes one item of the object collection. To map it onto the Schema, either Mapping (declarative, see Mapping) or Code (JavaScript) is used — as with the other service-based providers, the two are mutually exclusive.
When accessing the attributes:
- The distinguished name of the entry is always available as
dn, even whenAttributesis set. - Multi-valued attributes (e.g.
memberOf) are joined into a single value, separated by"; ".
Binary attributes such as objectGUID or objectSid are decoded as UTF-8 and are therefore not usable in a meaningful way. For a stable identifier, use dn.
Security
- Use
ldaps://whenever a service account is configured. With a simple bind over plain LDAP (ldap://, port 389) the password is transmitted unencrypted, and the server logs a warning. Without configured credentials the warning does not apply, because no password is transmitted. - Use a service account with minimal permissions — read access to the required subtree is sufficient. The same applies to the server process account when no credentials are configured.
- Enable
IgnoreCertificateErrorsin test environments only. When the option is set, the server logs a warning because the server certificate is not validated.
Limitations
- The supported bind methods are simple bind (with
UserName/Password) and Negotiate (without credentials, as the server process account). An anonymous bind is not supported. - Automatic server discovery always uses plain LDAP on port 389. An encrypted connection requires
Serverto be set withldaps://. - StartTLS is not supported; encrypted connections use
ldaps://. - If the server truncates the result (size limit exceeded), the entries delivered up to that point are used and a warning is logged.
Use in Connect Session Templates
The LdapDataProvider is also available as an initializer in Connect Session Templates, to pre-populate a form with directory data when it is opened. The query parameters of the launching URL are forwarded automatically as search data and resolve the {placeholder} tokens in the filter. As with the other initializers, the transformation happens in the Code element; Mapping is not supported there.
Example XML configuration
Selecting a cost-centre approver from the Active Directory, restricted to one organisational unit:
<ObjectCollection Id="Approver" Label="Approver">
<Schema>
<Text Id="FullName" Label="Name" />
<Text Id="Email" Label="Email" />
<Text Id="Phone" Label="Phone" />
<Text Id="Department" Label="Department" />
</Schema>
<Summary>
<Field Id="FullName" />
<Field Id="Department" />
</Summary>
<DataProviders>
<LdapDataProvider DisplayName="Active Directory">
<SearchParameters>
<Text Id="name" Label="Name" />
</SearchParameters>
<Options>
<Server>ldaps://dc01.example.com</Server>
<UserName>service@example.com</UserName>
<Password>{EncryptedPassword}</Password>
<BaseDn>OU=Finance,OU=Users,DC=example,DC=com</BaseDn>
<Filter><![CDATA[(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(|(sn={name}*)(givenName={name}*)))]]></Filter>
<Attributes>displayName,mail,telephoneNumber,department</Attributes>
<Scope>Subtree</Scope>
<SizeLimit>50</SizeLimit>
</Options>
<Mapping>
<Map Source="displayName" Target="FullName" />
<Map Source="mail" Target="Email" />
<Map Source="telephoneNumber" Target="Phone" />
<Map Source="department" Target="Department" />
</Mapping>
</LdapDataProvider>
</DataProviders>
</ObjectCollection>
If the filter contains characters such as &, < or >, a <![CDATA[ … ]]> block is recommended — the filter stays readable and does not have to be written using XML entities (&).