# Manage Directory Users and Groups Active Directory Plugin lets a workflow create and delete LDAP users and groups, change direct group membership, and check the resulting directory state. This guide uses one verifiable example: add the user named by `DirectoryUserName` to the `admin` group, then continue only when a live LDAP condition confirms that direct membership. **Prerequisites:** - [Configure LDAP Sources](https://docs.workflowengine.io/plugins/active-directory-plugin/configure-ldap-sources/) - register a source with the correct user and group search bases. - [Action](https://docs.workflowengine.io/get-started/concepts/action/) - understand where a workflow activity runs plugin actions. - A test directory or OU where the bind identity can create, modify, and delete objects. ## Protect writable directories Directory management actions write directly to the user and group locations configured for their LDAP source. :::warning Use a writable directory Use a dedicated writable OU, LDAPS, and a bind identity restricted to the required operations. Do not target synchronized objects in `OU=AADDC Users` in Microsoft Entra Domain Services; managed-domain writes do not change Microsoft Entra ID. ::: ## Configure a management action A management action runs when Workflow Engine executes its containing activity. In this example, the action reads a [process parameter](https://docs.workflowengine.io/get-started/concepts/parameter/) and adds that directory user to a group selected from `local-ldap`. 1. Add a string process parameter named `DirectoryUserName`. Use `Test User` while testing. 2. Open an activity and create an action implementation. 3. Select `ActiveDirectoryAddUserToGroup` as the action. 4. Set **User name** to `@DirectoryUserName`. 5. Set **Group name** to `Group: admin | Source: local-ldap`. Designer parameter editor for ActiveDirectoryAddUserToGroup with DirectoryUserName and the admin group from local-ldap Text action fields accept `@ParameterName` substitutions. The group selector stores both the group and source, so the action can resolve `admin` in `local-ldap` without a separate source field. ### Available management actions Active Directory Plugin registers these management actions: | Action | Required input | Result | |--------|----------------|--------| | `ActiveDirectoryCreateUser` | User name and source; configured user attributes are optional | Creates a user in the source's user location | | `ActiveDirectoryDeleteUser` | User name and source | Deletes the matching user if it exists | | `ActiveDirectoryCreateGroup` | Group name, source, and user names; configured group attributes are optional | Creates a group and adds every member that resolves | | `ActiveDirectoryDeleteGroup` | Group name and source | Deletes the matching group if it exists | | `ActiveDirectoryAddUserToGroup` | User name and selected group | Adds the user as a direct group member | | `ActiveDirectoryRemoveUserFromGroup` | User name and selected group | Removes the direct group membership | `ActiveDirectoryCreateGroup` separates user names at commas but does not trim them. Enter `Alice,Bob`, not `Alice, Bob`. Attributes enabled in the LDAP source appear as optional Designer fields for the corresponding create action. :::warning Complete AD DS account provisioning `ActiveDirectoryCreateUser` creates the directory object and writes configured attributes. It does not set an AD DS password or enable the account. Complete those steps outside Active Directory Plugin before treating the account as login-ready. See Microsoft's [user creation behavior](https://learn.microsoft.com/en-us/windows/win32/ad/creating-a-user). ::: :::warning Verify write results Delete actions make no change when an object is absent. Membership actions make no change when the user or group cannot be resolved, and group creation skips unresolved members. These outcomes do not prove that the requested state exists, so check the directory after an important write. ::: ## Use generated custom activities When [plugin registration enables custom activities](https://docs.workflowengine.io/plugins/active-directory-plugin/overview/#control-plugin-scope-and-availability), the Designer **Activities** palette contains one activity for each management action. Filter the palette by `ActiveDirectory` to find all six types. Designer Activities palette filtered to the six ActiveDirectory management activities Use a generated custom activity when one directory operation is the activity's main purpose. Use an ordinary activity implementation when the directory action must run with other actions. Both options execute the same operation and expose the same parameters. ## Branch on directory state A [transition condition](https://docs.workflowengine.io/get-started/concepts/condition/) can read LDAP immediately after a management activity and decide whether the process continues. For the running example, make the transition conditional, select `ActiveDirectoryIsUserInGroup`, and enter the same user and group values as the add action. Transition condition editor checking DirectoryUserName membership in the admin group from local-ldap Active Directory Plugin provides three directory conditions: - `ActiveDirectoryIsUserInGroup` returns `true` when the selected group directly contains the named user. - `ActiveDirectoryIsUserExists` returns `true` when the selected source contains the named user. - `ActiveDirectoryIsGroupExists` returns `true` when the selected source contains the named group. Each condition performs a live LDAP read. Active Directory Plugin does not cache condition results between evaluations or expand nested group membership. ## Review the complete process The `LdapManagement` process runs `ActiveDirectoryAddUserToGroup` in `ManageMembership`. Its automatic transition calls `ActiveDirectoryIsUserInGroup` and reaches `MembershipVerified` only when `Test User` is a direct member of `admin` in `local-ldap`. ![Directory membership process from ManageMembership through an LDAP membership check to MembershipVerified](https://docs.workflowengine.io/images/plugins/active-directory-plugin/manage-directory-users-and-groups/directory-membership-process.png)
Complete process scheme XML ```xml filename="LdapManagement.xml" ```
## Call the public .NET API The public `ActiveDirectoryMethods` field exposes the configured [IActiveDirectoryMethods][api-active-directory-methods] implementation. Application code can use the same source definitions without adding an action to a workflow scheme. ```csharp filename="DirectoryGroupReader.cs" using OptimaJet.Workflow.Plugins.ActiveDirectoryPlugin; public static class DirectoryGroupReader { public static IReadOnlyList GetDirectMemberNames( ActiveDirectoryPlugin plugin, string sourceName, string groupName) { return plugin.ActiveDirectoryMethods .GetAllUsersInGroup(groupName, sourceName) .Select(user => user.Name) .ToList(); } } ``` The API reference lists the complete read, write, membership, and source-inspection contract. The methods are synchronous, and directory client exceptions propagate to the caller. Active Directory Plugin does not expose these methods through Workflow Engine Web API. ## Verify a management workflow The example succeeds when both the process state and the LDAP state show the requested direct membership. 1. Before the test, confirm that `Test User` is not a direct member of `admin` in `local-ldap`. 2. Start the process with `DirectoryUserName` set to `Test User`. 3. Confirm that the process reaches the activity after the `ActiveDirectoryIsUserInGroup` transition. 4. Inspect `admin` with an LDAP administration tool or the public .NET API and confirm that `Test User` is a direct member. Run destructive create and delete tests only in a non-production OU with uniquely named test objects. Use the same LDAP implementation as production when testing directory-specific schema behavior. ## Troubleshoot directory operations Directory operation failures usually identify a mismatch between the action input, LDAP source configuration, and target directory permissions. | Symptom | Likely cause | Fix | |---------|--------------|-----| | A create action reports a required-attribute error | The directory schema requires an attribute absent from the source configuration | Configure the attribute and provide its value in the action | | The second user in a new group is not found | The user list contains a space after the comma | Enter exact names separated by commas without padding | | An action reads but cannot write | The bind identity is read-only or the target OU is managed | Select a writable OU and grant only the required write rights | | A membership transition does not run | The user or group name does not match the configured common-name attribute | Verify both names and the source selected with the group | ## Frequently asked questions **Can Active Directory Plugin action fields use workflow parameters?** Yes. Text fields accept substitutions such as `@DirectoryUserName`. The process parameter value is resolved when Workflow Engine executes the action or condition. **Do Active Directory Plugin actions change Microsoft Entra ID?** No. Writes to Microsoft Entra Domain Services do not synchronize back to Microsoft Entra ID. Use a Microsoft Entra management API when Microsoft Entra ID is the system of record. **What is the difference between a directory action and a generated custom activity?** A directory action can run with other actions in an ordinary activity. A generated custom activity wraps the same single operation as a dedicated Designer activity type. **Can application code manage the directory without a workflow action?** Yes. Application code can call `ActiveDirectoryPlugin.ActiveDirectoryMethods` directly with the same provider and source configuration used by the plugin actions and conditions. [api-active-directory-methods]: https://api.workflowengine.io/active-directory-plugin/OptimaJet.Workflow.Plugins.ActiveDirectoryPlugin.Providers/IActiveDirectoryMethods/