---
title: Configuring <code>ldapGroups</code> in the LDAP connector
description: The LDAP Connector includes a special virtual attribute, ldapGroups, which simplifies managing LDAP group memberships. This topic explains the functionality of ldapGroups, provides configuration instructions, details important considerations, and best practices.
component: openicf
page_id: openicf:connector-reference:ldapgroups
canonical_url: https://docs.pingidentity.com/openicf/connector-reference/ldapgroups.html
section_ids:
  ldapgroups-membership: LDAP group membership
  example_memberof_in_ad: "Example: memberOf in AD"
  example_ismemberof_in_pingds_ds: "Example: isMemberOf in PingDS (DS)"
  ldapgroups-overview: "ldapGroups: A connector-level solution"
  ldapgroups-configuring: Configuration
  1_add_ldapgroups_to_the_connector_schema: 1. Add ldapGroups to the connector schema
  2_update_user_mapping: 2. Update user mapping
  example_assigning_ad_groups_using_roles: "Example: Assigning AD groups using roles"
  ldapgroups-performance: Performance and functional considerations
  performance_cost: Performance cost
  functional_limitations_default_behavior: Functional limitations (default behavior)
  ldapgroups-comparison: ldapGroups compared to memberOf and isMemberOf
  ldapgroups-parameter: The ldapGroupsUseStaticGroups parameter
  base_context_filtering: Base context filtering
  ad_considerations: AD considerations
  ldapgroups-best-practices: Recommendations and best practices
---

# Configuring `ldapGroups` in the LDAP connector

The LDAP Connector includes a special virtual attribute, `ldapGroups`, which simplifies managing LDAP group memberships. This topic explains the [functionality of `ldapGroups`](#ldapgroups-membership), [provides configuration instructions](#ldapgroups-configuring), details [important considerations](#ldapgroups-performance), and [best practices](#ldapgroups-best-practices).

## LDAP group membership

In standard LDAP directories, such as PingDS or Active Directory (AD), directory servers typically store group membership information on the **group** entry, not the **user** entry. A group object contains a list of its members, often as distinguished names (DNs) pointing to user entries (for example, using the `member` or `uniqueMember` attribute).

By default, a user entry doesn't list the groups to which it belongs, so a client application could need to search numerous group entries to determine a user's group memberships. To simplify this process, most directory servers provide a **computed** attribute on the user entry that dynamically lists the groups where the user is a member.

* In **PingDS**, this attribute is `isMemberOf`.

* In **AD**, this attribute is `memberOf`.

These attributes are valuable for reading membership information but are **read-only**. You cannot directly modify a user's `memberOf` or `isMemberOf` attribute to change group memberships; you must modify the actual group entry's member list.

### Example: `memberOf` in AD

A query for an AD user might return:

```
dn: CN=user five,OU=test1,DC=example,DC=com
...
memberOf: CN=testgroup,OU=test1,DC=example,DC=com
...
```

### Example: `isMemberOf` in PingDS (DS)

A query for a DS user, requesting the `isMemberOf` attribute, might return:

```
dn: uid=user.3,ou=People,dc=example,dc=com
...
isMemberOf: cn=Test Group,ou=groups,dc=example,dc=com
...
```

|   |                                                                                                                                                                                                    |
| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Directory servers often do not return these calculated attributes by default because their computation incurs a performance cost. You typically need to request these attributes in LDAP searches. |

## `ldapGroups`: A connector-level solution

The `ldapGroups` attribute is a feature **specific to the LDAP Connector**. It functions as a writable proxy for managing group memberships directly using the user object within IDM.

When you map and use `ldapGroups`:

* **Reads (GET operations):** The connector determines the user's group memberships. By default, it does this by searching group entries on the target directory for the user's DN (for example, searching for `(member=<userDN>)` or `(uniqueMember=<userDN>)`).

* **Writes (Update operations):** When you add or remove group DNs from the `ldapGroups` attribute in IDM and save the user object, the connector translates these changes into the necessary LDAP modify operations against the **group** entries on the target directory (adding or removing the user's DN from the group's member list).

This mechanism lets you manage group assignments within IDM (for example, through role assignments) without directly interacting with group objects.

## Configuration

To use `ldapGroups`, configure it in the LDAP connector's provisioner file (`provisioner.openicf-ldap.json` or similar) and include it in the user object mapping.

### 1. Add `ldapGroups` to the connector schema

Add the following definition to the `account` object type within the connector configuration's `objectTypes` section:

```json
"ldapGroups" : {
  "type" : "array",
  "nativeType" : "string",
  "nativeName" : "ldapGroups",
  "required" : false,
  "items" : {
    "type" : "string",
    "nativeType" : "string"
  }
}
```

### 2. Update user mapping

The goal of this step is to produce a list of group DN values for `ldapGroups` during the synchronization process. There are a variety of methods which you can use, including:

* Property mappings

* An `onUpdate` script

* Role assignment processing

Ensure the synchronization mapping (`sync.json`) for the user object includes a mapping for `ldapGroups`. For example:

```json
{
    "source": "ldapGroups",
    "target": "ldapGroups"
}
```

If you manage assignments using roles, configure the role assignment to target the `ldapGroups` attribute. You can also grant roles to users directly. Learn more in [Roles](https://docs.pingidentity.com/pingidm/8/objects-guide/roles.html) in the PingIDM documentation.

### Example: Assigning AD groups using roles

1. Configure the connector and mapping as described previously.

2. Create an internal role (for example, "AD Finance Group Users").

3. In the admin UI, navigate to the role's Managed Assignments (or equivalent section).

4. Create a new assignment targeting the appropriate AD connector or mapping.

5. Select the `ldapGroups` attribute.

6. Select the desired AD group (for example, `CN=Finance Users,OU=Groups,DC=example,DC=com`) from the provided list.

7. Save the assignment and the role.

Assigning this IDM role to a user automatically adds that user to the specified AD group. Learn more in [Working with role assignments](https://docs.pingidentity.com/pingidm/8/objects-guide/working-with-role-assignments.html) in the PingIDM documentation.

## Performance and functional considerations

Although `ldapGroups` offers convenience, it's crucial to understand its implications.

### Performance cost

* **Default read behavior:** By default, `ldapGroups` requires the connector to search group entries on the target directory. This makes read operations (such as GET User or reconciliation) consume more resources. The connector performs an additional search for each user to identify the **static** groups they belong to. This slows performance when querying for many users with `ldapGroups` included or, to a lesser extent, users who are members of many groups.

* **Update behavior:** Updates involving `ldapGroups` also add overhead. The connector must determine the user's current group memberships (often involving another search), calculate the difference between the current state and the desired state, and then execute LDAP modify operations on the relevant group entries. This can slow performance when updating groups with many members.

### Functional limitations (default behavior)

* **Static groups only:** By default, `ldapGroups` discovers and manages only memberships in **static** groups (those that have explicit `member` or `uniqueMember` attributes). It does **not** recognize or manage memberships from:

* **Dynamic groups:** Groups where rules or LDAP URLs determine membership (common in DS).

* **Nested groups:** Groups that contain other groups as members.

* **Incomplete view:** Relying **only** on `ldapGroups` (using default settings) to ascertain a user's effective group memberships might give an incomplete picture if your environment uses dynamic or nested groups.

### `ldapGroups` compared to `memberOf` and `isMemberOf`

|                |                                       |                                            |
| -------------- | ------------------------------------- | ------------------------------------------ |
| Feature        | `ldapGroups`                          | `memberOf` and `isMemberOf`                |
| **Purpose**    | Read/write proxy for group membership | Read-only view of group membership         |
| **Scope**      | Static groups only                    | All group types (static, dynamic, nested)  |
| **Writable?**  | Yes (using connector logic)           | No (read-only virtual attribute)           |
| **Read cost**  | Higher (connector searches groups)    | Lower (directory calculates; often faster) |
| **Managed by** | LDAP Connector                        | Target directory server                    |

### The `ldapGroupsUseStaticGroups` parameter

To address performance and functional limitations, the LDAP connector includes the `ldapGroupsUseStaticGroups` configuration parameter (located in the main connector configuration file, `provisioner.openicf-ldap.json`).

* **`false` (default):** `ldapGroups` operates as described previously, searching static group entries. This approach is safer for updates involving mixed group types but has performance drawbacks and limits visibility to static groups.

* **`true`:** `ldapGroups` uses the directory's `memberOf` (AD) or `isMemberOf` (DS) virtual attribute for **reading** group memberships.

* **Pros:** Improves read and query performance; includes dynamic and nested groups in the results that `ldapGroups` returns.

* **Cons:** **Presents high risk for updates.** If IDM tries to modify memberships derived from dynamic or nested groups (which `isMemberOf` or `memberOf` might return), the connector could attempt inappropriate LDAP operations (such as modifying a dynamic group as if it were static). This can lead to errors (for example, DS schema violation code 65) and failed updates. Use this setting only if the environment exclusively uses static groups and you have thoroughly tested it.

### Base context filtering

* When `ldapGroupsUseStaticGroups` is `false` (default), the connector's search for static groups follows the `baseContexts` defined in the connector configuration. The connector considers only groups within these specified base contexts.

* When `ldapGroupsUseStaticGroups` is `true`, the `memberOf` or `isMemberOf` attribute returns **all** groups the user belongs to, regardless of the connector's `baseContexts` setting. This happens because the directory server typically does not filter the virtual attribute itself by base context.

### AD considerations

* AD primarily uses static groups, which makes the default `ldapGroups` behavior suitable.

* AD's `memberOf` attribute does **not** natively display nested memberships unless the query includes a specific LDAP control (LDAP\_SERVER\_CHAINING\_OID: `1.2.840.113556.1.4.1941`). The connector's use of `memberOf` (when `ldapGroupsUseStaticGroups` is true) might or might not retrieve nested memberships, depending on internal implementation specifics.

## Recommendations and best practices

1. **Understand the trade-offs:** Recognize that `ldapGroups` offers convenience but affects performance and potentially adds complexity, particularly when different group types exist in the environment.

2. **Prefer `memberOf` or `isMemberOf` for reading:** To view a user's complete group memberships, you should map the directory's native `memberOf` or `isMemberOf` attribute as read-only (`"flags": ["NOT_CREATABLE", "NOT_UPDATEABLE"]`). This method is generally more efficient and comprehensive than reading `ldapGroups`.

3. **Use `ldapGroups` cautiously for writing:** If IDM must manage group memberships:

   * Keep the `ldapGroupsUseStaticGroups` setting as `false` (the default) unless you confirm the environment uses **only** static groups and you've performed comprehensive testing.

     |   |                                                                                                                                                                                                                                                                                                                                        |
     | - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
     |   | If you can't guarantee that only static groups are used and want to update the static groups, use a transform script. Create logic which filters all of the non-static groups from the `isMemberOf` group DN list. This allows you make reasonable updates to static groups without the high performance cost of reading `ldapGroups`. |

   * Consider adding the `"flags": ["NOT_RETURNED_BY_DEFAULT"]` to the `ldapGroups` definition within the provisioner file. This flag prevents the performance degradation that calculating `ldapGroups` causes during default read operations, such as reconciliation synchronization checks, while still allowing you to use it explicitly in updates or specific requests.

   * Add the `NOT_RETURNED_BY_DEFAULT` flag to optimize read performance:

     ```json
     {
       "ldapGroups": {
         "type": "array",
         "nativeType": "string",
         "nativeName": "ldapGroups",
         "required": false,
         "items": {
           "type": "string",
           "nativeType": "string"
         },
         "flags": [
           "NOT_RETURNED_BY_DEFAULT"
         ]
       }
     }
     ```

4. **Index directory attributes:** Ensure the directory server indexes the `member` (AD) or `uniqueMember` (DS) attributes on group objects. Indexing is critical to lessen the performance impact when `ldapGroups` searches static groups (`ldapGroupsUseStaticGroups: false`). Consult the directory server documentation for indexing best practices.

5. **Alternative: Manage group objects:** The most technically direct LDAP approach involves managing memberships by modifying the group objects directly within IDM (assuming you synchronize group objects). However, this method often requires more complex configuration and scripting compared to using `ldapGroups` through role assignments.

By understanding how `ldapGroups` operates and its associated trade-offs, you can configure it effectively to meet group management requirements while minimizing performance impacts and avoiding potential issues.
