Skip to main content

Directory Sync

Directory sync automates user and group provisioning from your organization's upstream identity source — Active Directory, LDAP, or a cloud IdP. Changes in your directory (new hires, departures, department transfers, group membership changes) propagate to Ithbat IAM automatically, keeping both systems consistent without manual intervention.


Supported directory sources

SourceProtocolNotes
Microsoft Active DirectoryLDAP/LDAPSOn-premises AD via secure LDAP
Azure AD / Entra IDSCIMVia the built-in SCIM provisioning in Azure
Google WorkspaceSCIMVia Google's SCIM provisioning connector
OktaSCIMVia Okta's SCIM provisioning feature
JumpCloudSCIMVia JumpCloud's SCIM connector
Generic LDAPLDAP/LDAPSAny LDAP v3-compatible directory

For cloud IdPs (Azure AD, Okta, Google, JumpCloud), configure SCIM provisioning on the IdP side and point it at Ithbat's SCIM endpoint. See SCIM 2.0 for those setup guides.

This page covers the Directory Sync feature for on-premises LDAP/AD sources, which is managed from the Ithbat admin console independently of SCIM.


How directory sync works

sequenceDiagram
participant AD as Active Directory / LDAP
participant Ithbat as Ithbat IAM
participant Admin as Admin Console

Admin->>Ithbat: Create directory connection
Ithbat->>AD: Test LDAP bind
AD-->>Ithbat: Bind successful
loop Sync job (scheduled or manual)
Ithbat->>AD: LDAP query users + groups
AD-->>Ithbat: User and group records
Ithbat->>Ithbat: Diff against current state
Ithbat->>Ithbat: Create / update / deactivate users
Ithbat->>Ithbat: Update group memberships
end
Admin->>Ithbat: View sync job results

Sync runs on a configurable schedule. You can also trigger a manual sync at any time from the admin console or API.


Creating a directory connection

Via admin console

  1. Go to Settings → Directory Sync → Add Connection.
  2. Select the directory type (Active Directory, Generic LDAP).
  3. Fill in the connection details (see fields below).
  4. Click Test Connection to verify credentials.
  5. Click Save.

Via API

POST /api/v1/directories
Authorization: Bearer {token}
X-Tenant-ID: {tenant_id}
Content-Type: application/json

{
"name": "Corporate AD",
"type": "active_directory",
"host": "ldap.acme.com",
"port": 636,
"useTLS": true,
"bindDN": "CN=ithbat-sync,OU=ServiceAccounts,DC=acme,DC=com",
"bindPassword": "s3cr3t!",
"baseDN": "DC=acme,DC=com",
"userSearchFilter": "(objectClass=person)",
"groupSearchFilter": "(objectClass=group)",
"syncSchedule": "0 */4 * * *"
}

Connection fields

FieldDescription
nameA display name for this connection
typeactive_directory or ldap
hostLDAP server hostname or IP
port389 for LDAP, 636 for LDAPS
useTLSUse LDAPS (TLS). Strongly recommended for production
bindDNThe Distinguished Name of the service account used to query the directory
bindPasswordPassword for the bind account
baseDNThe DN from which user and group searches are performed
userSearchFilterLDAP filter for user objects. Default: (objectClass=person)
groupSearchFilterLDAP filter for group objects. Default: (objectClass=group)
syncScheduleCron expression for automatic sync. Leave empty to disable automatic sync

Sync scheduling

The syncSchedule field accepts a standard cron expression (5-field, UTC):

ExpressionRuns
0 */4 * * *Every 4 hours
0 2 * * *Daily at 02:00 UTC
0 0 * * 1Weekly on Monday at midnight

To disable scheduled sync and run only manually, omit syncSchedule or set it to an empty string.


Triggering a manual sync

Via admin console

  1. Go to Settings → Directory Sync → {connection name}.
  2. Click Sync Now.

Via API

POST /api/v1/directories/{id}/sync
Authorization: Bearer {token}

Response:

{
"jobId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"status": "running",
"startedAt": "2026-02-24T10:00:00Z"
}

Monitoring sync status

List all connections

GET /api/v1/directories
Authorization: Bearer {token}
X-Tenant-ID: {tenant_id}

Get a connection

GET /api/v1/directories/{id}
Authorization: Bearer {token}

List sync jobs for a connection

GET /api/v1/directories/{id}/jobs
Authorization: Bearer {token}

Response includes a list of sync jobs, each with:

{
"id": "9b1deb4d-...",
"directoryId": "3fa85f64-...",
"status": "completed",
"usersCreated": 5,
"usersUpdated": 12,
"usersDeactivated": 1,
"groupsCreated": 2,
"groupsUpdated": 3,
"errors": [],
"startedAt": "2026-02-24T10:00:00Z",
"completedAt": "2026-02-24T10:00:45Z"
}

Get a specific sync job

GET /api/v1/directories/{id}/jobs/{jobId}
Authorization: Bearer {token}

Sync behavior

When a sync job runs, Ithbat compares the LDAP query results against the current state of users and groups in the tenant:

Change in directoryAction in Ithbat
New user in LDAPUser account created in Ithbat with emailVerified: true
User attribute changedProfile updated (firstName, lastName, email, phone)
User disabled/deactivated in ADUser account suspended in Ithbat; active sessions invalidated
User deleted from ADUser account suspended in Ithbat (not deleted, to preserve audit history)
Group createdGroup created in Ithbat
Member added to groupUser added to the corresponding Ithbat group
Member removed from groupUser removed from the corresponding Ithbat group
note

Ithbat suspends deleted directory users rather than deleting them, preserving audit logs and allowing re-activation if needed. To permanently delete a user, do so manually from the admin console after confirming with your security team.


Attribute mapping

Ithbat maps LDAP attributes to user profile fields. Default mappings for Active Directory:

Ithbat fieldAD attribute
emailmail
firstNamegivenName
lastNamesn
phonetelephoneNumber
displayNamedisplayName
externalIdobjectGUID

For generic LDAP or if your AD schema uses different attribute names, provide custom mappings in the directory configuration:

PUT /api/v1/directories/{id}
Authorization: Bearer {token}
Content-Type: application/json

{
"attributeMapping": {
"email": "mail",
"firstName": "givenName",
"lastName": "sn",
"phone": "mobile",
"externalId": "entryUUID"
}
}

Conflict resolution

When a conflict arises between a directory-sourced attribute and a value that was manually edited in Ithbat:

  • Directory wins for attributes covered by the attribute mapping (email, firstName, lastName, phone). The next sync overwrites local changes for these fields.
  • Ithbat wins for attributes not in the mapping (metadata, custom fields, role assignments). The directory sync does not touch these.

If you need to keep a user's profile out of sync intentionally (e.g., a legal name change), remove the user from the directory's managed scope or configure an exclusion filter.


Testing the connection

Before creating a sync job, verify that Ithbat can reach your LDAP server:

POST /api/v1/directories/{id}/test
Authorization: Bearer {token}

Response:

{
"success": true,
"usersFound": 247,
"groupsFound": 18
}

If the test fails, the response includes an error message indicating whether the failure was a network issue, an authentication failure, or an invalid base DN.


Updating and deleting connections

Update a connection

PUT /api/v1/directories/{id}
Authorization: Bearer {token}
Content-Type: application/json

{
"syncSchedule": "0 1 * * *",
"bindPassword": "new-password"
}

Delete a connection

Deleting a connection does not delete the users or groups that were synced. Future syncs from this source will no longer run.

DELETE /api/v1/directories/{id}
Authorization: Bearer {token}

Directory Sync API reference

MethodEndpointPermission
GET/api/v1/directoriesdirectory:read
GET/api/v1/directories/{id}directory:read
GET/api/v1/directories/{id}/jobsdirectory:read
GET/api/v1/directories/{id}/jobs/{jobId}directory:read
POST/api/v1/directoriesdirectory:write
PUT/api/v1/directories/{id}directory:write
DELETE/api/v1/directories/{id}directory:write
POST/api/v1/directories/{id}/testdirectory:write
POST/api/v1/directories/{id}/syncdirectory:write

Next steps

  • SCIM 2.0 — use SCIM provisioning for cloud IdPs instead of LDAP
  • User Management — manage users created by directory sync
  • Audit Logs — view sync events and changes to user accounts