Skip to Content
Evaluate Get Started Plugins Glossary

Configure LDAP Sources

Key takeaways

Configure one ActiveDirectorySource for each LDAP endpoint, give every source a unique name, and set both its UsersSource and GroupSource. For Microsoft Entra ID, connect to Microsoft Entra Domain Services over LDAPS and use explicit search base DNs. Register ActiveDirectoryPlugin before WorkflowRuntime.StartAsync.

The worked example uses Microsoft Entra Domain Services. For AD DS or another compatible LDAP server, keep the same source structure and replace the endpoint, schema presets, and search base DNs.

Prerequisites:

  • Active Directory Plugin overview - confirm that the LDAP integration boundary fits the application.
  • Workflow Runtime - configure the builder, persistence provider, and runtime services.
  • A license that includes the Active Directory feature.
  • A reachable LDAP endpoint and its directory schema and search base DNs.
  • A bind identity with the required read or write permissions when the server does not permit the required access without explicit credentials.

Install the plugin package

The WorkflowEngine.NETCore-ActiveDirectoryPlugin package supplies ActiveDirectoryPlugin, ActiveDirectorySource, and both built-in LDAP implementations.

dotnet add package WorkflowEngine.NETCore-ActiveDirectoryPlugin

The package namespace is OptimaJet.Workflow.Plugins.ActiveDirectoryPlugin.

Configure Microsoft Entra Domain Services

ActiveDirectorySource combines connection settings with a user search definition and a group search definition. SetUsersSource(...) and SetGroupsSource(...) configure those search mappings. For Microsoft Entra ID, enable Microsoft Entra Domain Services and secure LDAP first, then use the managed domain's LDAPS DNS name and port 636. Microsoft's LDAPS tutorial covers the certificate, networking, and managed-domain prerequisites.

Replace the example host, DNs, and bind identity with values from the managed domain. Supply the password from the application's secret provider.

ActiveDirectoryRegistration.cs
using OptimaJet.Workflow.Core.Runtime;using OptimaJet.Workflow.Plugins.ActiveDirectoryPlugin;public static class ActiveDirectoryRegistration{    public static WorkflowRuntime AddEntraDirectory(        this WorkflowRuntime runtime,        string bindPassword)    {        const string domainDn = "DC=aaddscontoso,DC=com";        const string directoryDn = "OU=AADDC Users,DC=aaddscontoso,DC=com";        var source = new ActiveDirectorySource(                "entra-domain-services",                "ldaps.aaddscontoso.com",                636,                isSecureConnection: true)            .SetAuth(                "CN=Workflow Reader,OU=AADDC Users," + domainDn,                bindPassword)            .SetUsersSource(UsersSource.ADUserDn(directoryDn))            .SetGroupsSource(GroupSource.ADGroupDn(directoryDn));        return runtime.WithPlugin(new ActiveDirectoryPlugin(source));    }}
Microsoft Entra Domain Services bind accounts

The bind identity must be synchronized to the managed domain and have Kerberos and NTLM password hashes. A user created in Microsoft Entra ID is not synchronized to Domain Services until the user changes their password. Confirm that the bind account is in the synchronization scope, change its password when required, and wait for synchronization before testing LDAP authentication. See Microsoft's credential synchronization behavior.

Do not write to the synchronized OU

The example points both search bases to the synchronized OU=AADDC Users container. Use this source for authorization reads. To create or manage locally owned objects, configure another source whose search bases point to a writable custom OU. See Manage Directory Users and Groups.

Set the source connection

ActiveDirectorySource stores connection and bind settings for one endpoint. Every configured source must also receive both a UsersSource and a GroupSource; accessing either property before setting it throws an exception.

Member or methodDefaultEffect
NameRequiredIdentifies the source in Designer values and runtime calls
HostRequiredSets the LDAP server DNS name or address
PortRequiredSets the LDAP port, commonly 636 for LDAPS
IsSecureConnectionfalseEnables the built-in client's secure LDAP mode
User, PasswordnullSupply the credential values passed to the selected directory client
SetAuth(user, password)Not calledStores the bind identity and password passed to the selected directory client
SetUsersSource(...)Not setDefines where and how users are read and created
SetGroupsSource(...)Not setDefines where and how groups are read and created

Choose the LDAP implementation

LdapImplementation is selected when ActiveDirectoryPlugin is created. NovellLdap is the cross-platform default. Use DirectoryServices only for a Windows-hosted application that specifically requires System.DirectoryServices. All sources in one plugin instance use the same implementation. See Compare the LDAP implementations for differences in bind and lookup behavior.

Protect credentials and network access

SetAuth stores the credential strings on the in-memory source object. The plugin does not encrypt or persist that configuration. Keep the bind password outside source code, load it from the host application's secret provider, and do not log or serialize the source object. Grant the bind identity only the directory permissions required by the selected operations.

Use LDAPS to protect bind credentials and directory traffic. The application host must trust the issuing certificate authority, and the endpoint hostname must match the certificate. Keep the LDAP endpoint on a private network when possible. If Microsoft Entra Domain Services secure LDAP is exposed over the public internet, restrict inbound TCP port 636 to known source IP addresses with network security group or firewall rules.

Configure user and group searches

UsersSource and GroupSource map the directory schema to the plugin models and define the bases used for reads and writes.

Use explicit search base DNs

Prefer the explicit DN factory methods so the configured search location is visible in code.

FactorySearch baseSchema defaults
UsersSource.ADUserDn(usersDn)Uses usersDn exactlycn, memberOf, object classes user and person
GroupSource.ADGroupDn(groupsDn)Uses groupsDn exactlyFilter (objectClass=group), cn, member
UsersSource.LDAPUserDn(usersDn)Uses usersDn exactlycn, memberOf, object classes inetOrgPerson and person
GroupSource.LDAPGroupDn(groupsDn)Uses groupsDn exactlyFilter (objectClass=groupOfNames), cn, member

The base-DN convenience methods add fixed containers. UsersSource.ADBaseDn(baseDn) searches CN=Users, while GroupSource.ADBaseDn(baseDn) searches CN=Builtin. UsersSource.LDAPBaseDn(baseDn) adds ou=users, and GroupSource.LDAPBaseDn(baseDn) adds ou=roles. Use the explicit methods when the directory stores objects elsewhere, including OU=AADDC Users in Microsoft Entra Domain Services.

The generic LDAP user preset also initializes sn from the requested user name during creation. The AD user preset defines no default attribute initializer.

Map a custom schema

For a custom schema, construct UsersSource or GroupSource directly and configure these members:

ConfigurationPurpose
SearchBaseDnSets the root for supported subtree searches and the parent DN used for created objects and constructed write-operation DNs
CommonNameAttributeSupplies the attribute mapped to the plugin object's Name
ObjectClassesSupplies object classes written when a user or group is created
UsersSource.MemberOfAttributeNames the user attribute that contains group DNs
UsersSource.LoadGroupMethodChooses how the provider populates ActiveDirectoryUser.Groups
GroupSource.SearchFilterFilters group enumeration, including Designer autocomplete
GroupSource.MemberAttributeNames the group attribute that contains member DNs
AttributesLoads extra attributes and adds optional fields to Designer create operations
AttributeInitializersCalculates user attributes during creation; NovellLdap also applies group initializers, while DirectoryServices does not

When the plugin loads a user, it can build the user's group list in two ways:

  • The AD preset reads the groups listed in the user's memberOf attribute.
  • The generic LDAP preset searches the configured groups and checks their direct members for that user.

This choice affects only the group list returned with a user. It does not change command authorization: the ActiveDirectoryGroup rule always checks the direct members of the selected group.

Understand lookup and write locations

Both providers create users and groups directly below their configured SearchBaseDn and construct DNs there for write operations. DirectoryServices also resolves name-based user and group operations by binding to that exact constructed DN. NovellLdap searches below the configured base for name-based reads, but its writes still target the constructed DN. Keep objects that the plugin manages directly below the corresponding base when behavior must be consistent across providers.

Add more than one source

ActiveDirectoryPlugin accepts a List<ActiveDirectorySource>. Each source name must be unique because runtime and Designer lookups use that name as the key.

MultipleDirectoryRegistration.cs
using System.Collections.Generic;using OptimaJet.Workflow.Core.Runtime;using OptimaJet.Workflow.Plugins.ActiveDirectoryPlugin;public static class MultipleDirectoryRegistration{    public static WorkflowRuntime AddDirectories(        this WorkflowRuntime runtime,        ActiveDirectorySource entraSource,        ActiveDirectorySource partnerLdapSource)    {        var sources = new List<ActiveDirectorySource>        {            entraSource,            partnerLdapSource        };        return runtime.WithPlugin(            new ActiveDirectoryPlugin(                sources,                LdapImplementation.NovellLdap));    }}

Verify the source configuration

Open the Designer group selector and choose the configured source. Confirm that a known group appears in autocomplete. This verifies the endpoint, bind credentials, and group search settings.

Workflow Designer autocomplete showing the admin group from the local-ldap source for an ActiveDirectoryGroup actor

Group discovery does not verify user lookup, membership matching, or write access. Follow Authorize Commands with Directory Groups to verify authorization, or Manage Directory Users and Groups to test a writable source.

Troubleshoot source configuration

ActiveDirectorySource failures usually come from endpoint security, a search base that does not contain the expected objects, or schema defaults that do not match the directory.

SymptomLikely causeFix
TLS connection failsThe certificate is untrusted, expired, or does not match the LDAPS hostnameInstall the required CA chain and use the certificate's DNS name
Bind failsThe bind identity format, password, or network access is wrongTest the same identity against the endpoint and confirm firewall rules
No groups appear, or a named user is not foundThe search base, common-name mapping, or group filter does not match the directoryUse explicit DNs and inspect the directory schema before changing preset fields
Users load without groupsThe directory does not populate memberOf as expectedSet LoadGroupMethod to UseGroupSearch and verify the group member attribute
Registration reports a duplicate keyTwo sources have the same NameGive every ActiveDirectorySource a unique name

Frequently asked questions

Which LDAP implementation should I use on Linux?

Use LdapImplementation.NovellLdap. It is the Active Directory Plugin default and works across supported .NET platforms. See Choose the LDAP implementation for the Windows alternative.

Should I use ADBaseDn for Microsoft Entra Domain Services?

Usually no. Use ADUserDn and ADGroupDn with the actual managed-domain OUs, as described in Use explicit search base DNs.

Can Active Directory Plugin use an anonymous LDAP bind?

With NovellLdap, omitting SetAuth passes unset credentials to the LDAP bind, so the server must permit that bind and access to every required attribute. DirectoryServices does not request an anonymous ADSI bind; with unset credentials, it uses the Windows caller's security context. IsAnonymous is changed only by SetAuth and does not change either provider's bind options. Call SetAuth when the application needs explicit and consistent credentials.

Can different sources use different LDAP implementations?

Not within one Active Directory Plugin instance. Its source-list constructor selects one LdapImplementation for the whole list. If one runtime must combine different directory backends, provide an IActiveDirectoryMethods implementation that delegates each source to the appropriate built-in provider. See the public-model limitation in the management guide.