LDAP
ldap authenticateldap authenticateldap searchldap searchldap userldap userldap groupsldap groupsldap testldap escape_filterldap escape_dn

ldap authenticate <config> <user> <password>


Description

    Check a login and a password: bind with the service account if bind_dn is given (else anonymous), search of the DN with the escaped login, exactly one entry required, new connection with the DN and the password of the user, closed at once. Returns {authenticated, dn, reason}: a wrong password, an unknown login and a refused account all give authenticated false, dn null and the same reason "invalid credentials" (AD sub-codes such as locked or expired are not told apart). Several entries give "ambiguous user: several entries match", an empty password "empty password refused" (without any connection). The server unreachable, TLS refused or a wrong service account are errors, not results. The answer is slower for a known login than for an unknown one (one more bind). By default the filter is (|(uid={0})(sAMAccountName={0})(userPrincipalName={0})(mail={0}))

Parameters

    config:   The connection as a JSON object: url, bind_dn, password or password_env, start_tls, timeout_ms, trust_all, base_dn, referrals, allow_plain - String - required
    user:   The login typed by the user (escaped by the function) - String - required
    password:   The password typed by the user - String - required
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "alice" "alicepw"
mentdb
{"authenticated": true, "dn": "uid=alice,ou=people,dc=example,dc=org", "reason": null}
Result of the UnboundID in-memory test server: a wrong password is a result, not an error
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "alice" "wrong"
mentdb
{"authenticated": false, "dn": null, "reason": "invalid credentials"}
Result of the UnboundID in-memory test server: a login which does not exist gives the same answer
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "nobody" "wrong"
mentdb
{"authenticated": false, "dn": null, "reason": "invalid credentials"}
Result of the UnboundID in-memory test server: a filter injection finds nothing
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "*)(uid=*" "alicepw"
mentdb
{"authenticated": false, "dn": null, "reason": "invalid credentials"}
Result of the UnboundID in-memory test server: two entries have this mail
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "twin@example.org" "twinpw"
mentdb
{"authenticated": false, "dn": null, "reason": "ambiguous user: several entries match"}
Result of the UnboundID in-memory test server: with a service account, by mail
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\", \"bind_dn\": \"cn=svc\", \"password\": \"svcpw\"}" "alice@example.org" "alicepw"
mentdb
{"authenticated": true, "dn": "uid=alice,ou=people,dc=example,dc=org", "reason": null}
Result of the UnboundID in-memory test server: with the password of the service account in an environment variable
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\", \"bind_dn\": \"cn=svc\", \"password_env\": \"LDAP_SVC_PASSWORD\"}" "alice" "alicepw"
mentdb
{"authenticated": true, "dn": "uid=alice,ou=people,dc=example,dc=org", "reason": null}
Result of the UnboundID in-memory test server: over LDAPS (self-signed certificate, trust_all for the test only)
admin
ldap authenticate "{\"url\": \"ldaps://localhost:21636\", \"base_dn\": \"dc=example,dc=org\", \"trust_all\": true, \"timeout_ms\": 3000}" "alice" "alicepw"
mentdb
{"authenticated": true, "dn": "uid=alice,ou=people,dc=example,dc=org", "reason": null}
Result of the UnboundID in-memory test server: with StartTLS
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"start_tls\": true, \"trust_all\": true, \"base_dn\": \"dc=example,dc=org\"}" "alice" "alicepw"
mentdb
{"authenticated": true, "dn": "uid=alice,ou=people,dc=example,dc=org", "reason": null}
An empty password is refused without any connection
admin
ldap authenticate "{\"url\": \"ldaps://ldap.example.org:636\", \"base_dn\": \"dc=example,dc=org\"}" "alice" ""
mentdb
{"authenticated": false, "dn": null, "reason": "empty password refused"}

ldap authenticate <config> <user> <password> <json_params>


Description

    Check a login and a password with parameters: user_filter (with {0} for the escaped login), base_dn (instead of the config), user_dn_template (with {0} for the login escaped as a DN value: no search and no service account, ex: uid={0},ou=people,dc=example,dc=org or {0}@corp.example.org)

Parameters

    config:   The connection as a JSON object: url, bind_dn, password or password_env, start_tls, timeout_ms, trust_all, base_dn, referrals, allow_plain - String - required
    user:   The login typed by the user (escaped by the function) - String - required
    password:   The password typed by the user - String - required
    json_params:   The parameters - String - required
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "bob" "bobpw" "{\"user_filter\": \"(&(objectClass=inetOrgPerson)(uid={0}))\"}"
mentdb
{"authenticated": true, "dn": "uid=bob,ou=people,dc=example,dc=org", "reason": null}
Result of the UnboundID in-memory test server: the DN is built from the login
admin
ldap authenticate "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "alice" "alicepw" "{\"user_dn_template\": \"uid={0},ou=people,dc=example,dc=org\"}"
mentdb
{"authenticated": true, "dn": "uid=alice,ou=people,dc=example,dc=org", "reason": null}

ldap user <config> <login>


Description

    One user found by login: {found: false} when there is none, an error when several entries match, else {found: true, dn, attributes...} with all the attributes and the fields of Active Directory when the directory gives them: disabled and password_never_expires (userAccountControl), locked_out and password_expired (msDS-User-Account-Control-Computed), password_last_set and password_must_change (pwdLastSet), password_expires (msDS-UserPasswordExpiryTimeComputed, null: never), account_expires (null: never). The dates are in UTC. On another directory these fields are absent

Parameters

    config:   The connection as a JSON object: url, bind_dn, password or password_env, start_tls, timeout_ms, trust_all, base_dn, referrals, allow_plain - String - required
    login:   The login (escaped by the function) - String - required
admin
ldap user "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "bob"
mentdb
{"found": true, "dn": "uid=bob,ou=people,dc=example,dc=org", "cn": "Bob Hoarau", "createTimestamp": "20261104040614.795Z", "creatorsName": "cn=Internal Root User", "entryDN": "uid=bob,ou=people,dc=example,dc=org", "entryUUID": "b98dd71c-5482-482e-8ee2-786421270c35", "mail": "bob@example.org", "modifiersName": "cn=Internal Root User", "modifyTimestamp": "20261104040614.795Z", "objectClass": "inetOrgPerson", "subschemaSubentry": "cn=schema", "uid": "bob"}
Result of the UnboundID in-memory test server: an entry with the attributes of Active Directory (values written on the test server, not a real AD)
admin
ldap user "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "jad"
mentdb
{"found": true, "dn": "cn=Jane Ad,ou=people,dc=example,dc=org", "accountExpires": "9223372036854775807", "cn": "Jane Ad", "createTimestamp": "20261104040614.798Z", "creatorsName": "cn=Internal Root User", "entryDN": "cn=jane ad,ou=people,dc=example,dc=org", "entryUUID": "c917c629-39ca-4322-9493-999365c7f98d", "modifiersName": "cn=Internal Root User", "modifyTimestamp": "20261104040614.798Z", "msDS-User-Account-Control-Computed": "8388624", "msDS-UserPasswordExpiryTimeComputed": "133500000000000000", "objectClass": "user", "objectGUID": "01020304-0506-0708-090a-0b0c0d0e0f10", "objectSid": "S-1-5-21-1004336348-1177238915-682003330-512", "pwdLastSet": "133000000000000000", "sAMAccountName": "jad", "subschemaSubentry": "cn=schema", "thumbnailPhoto": "gIE=", "userAccountControl": "514", "userPrincipalName": "jad@corp.example.org", "disabled": true, "password_never_expires": false, "locked_out": true, "password_expired": true, "password_must_change": false, "password_last_set": "2022-06-18T04:26:40Z", "password_expires": "2024-01-17T21:20:00Z", "account_expires": null}
Result of the UnboundID in-memory test server: not found
admin
ldap user "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "nobody"
mentdb
{"found": false}

ldap user <config> <login> <json_params>


Description

    One user with parameters: attributes (the computed fields need their source attributes), user_filter, base_dn, timeout_ms, binary_attributes

Parameters

    config:   The connection as a JSON object: url, bind_dn, password or password_env, start_tls, timeout_ms, trust_all, base_dn, referrals, allow_plain - String - required
    login:   The login (escaped by the function) - String - required
    json_params:   The parameters - String - required
admin
ldap user "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "jad" "{\"attributes\": [\"cn\", \"userAccountControl\"], \"user_filter\": \"(sAMAccountName={0})\"}"
mentdb
{"found": true, "dn": "cn=Jane Ad,ou=people,dc=example,dc=org", "cn": "Jane Ad", "userAccountControl": "514", "disabled": true, "password_never_expires": false}

ldap groups <config> <user_dn>


Description

    The groups of a user, nested: {user_dn, nested, count, truncated, groups: [{name, dn}]}. A walk level by level through member and uniqueMember: a cycle ends, 16 levels and 1000 groups at most (truncated true when cut)

Parameters

    config:   The connection as a JSON object: url, bind_dn, password or password_env, start_tls, timeout_ms, trust_all, base_dn, referrals, allow_plain - String - required
    user_dn:   The DN of the user - String - required
admin
ldap groups "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "uid=alice,ou=people,dc=example,dc=org"
mentdb
{"user_dn": "uid=alice,ou=people,dc=example,dc=org", "nested": true, "count": 3, "truncated": false, "groups": [{"name": "g1", "dn": "cn=g1,ou=groups,dc=example,dc=org"}, {"name": "g2", "dn": "cn=g2,ou=groups,dc=example,dc=org"}, {"name": "g3", "dn": "cn=g3,ou=groups,dc=example,dc=org"}]}

ldap groups <config> <user_dn> <json_params>


Description

    The groups with parameters: nested (true), ad (false; true: one query with the matching rule of AD 1.2.840.113556.1.4.1941, in pages of 500), base_dn, limit (1000, 10000 at most), max_depth (16, 32 at most), page_size, timeout_ms

Parameters

    config:   The connection as a JSON object: url, bind_dn, password or password_env, start_tls, timeout_ms, trust_all, base_dn, referrals, allow_plain - String - required
    user_dn:   The DN of the user - String - required
    json_params:   The parameters - String - required
admin
ldap groups "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "uid=alice,ou=people,dc=example,dc=org" "{\"nested\": false}"
mentdb
{"user_dn": "uid=alice,ou=people,dc=example,dc=org", "nested": false, "count": 1, "truncated": false, "groups": [{"name": "g1", "dn": "cn=g1,ou=groups,dc=example,dc=org"}]}
Result of the UnboundID in-memory test server: the walk stops at a depth
admin
ldap groups "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "uid=chain,ou=people,dc=example,dc=org" "{\"max_depth\": 2}"
mentdb
{"user_dn": "uid=chain,ou=people,dc=example,dc=org", "nested": true, "count": 2, "truncated": true, "groups": [{"name": "c0", "dn": "cn=c0,ou=groups,dc=example,dc=org"}, {"name": "c1", "dn": "cn=c1,ou=groups,dc=example,dc=org"}]}
Result of the UnboundID in-memory test server: Active Directory mode: the filter sent is (member:1.2.840.113556.1.4.1941:=the DN); the test server cannot walk this rule, its answer is simulated and this is not a real AD
admin
ldap groups "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}" "uid=alice,ou=people,dc=example,dc=org" "{\"ad\": true}"
mentdb
{"user_dn": "uid=alice,ou=people,dc=example,dc=org", "nested": true, "count": 2, "truncated": false, "groups": [{"name": "adg1", "dn": "cn=adg1,ou=groups,dc=example,dc=org"}, {"name": "adg2", "dn": "cn=adg2,ou=groups,dc=example,dc=org"}]}

ldap test <config>


Description

    Test a connection and read the RootDSE: {ok, latency_ms, vendor, vendor_version, naming_contexts, default_naming_context, tls}, vendor "Active Directory" when an AD gives no vendor name. A failure (server unreachable, TLS refused, service account refused) gives {ok: false, latency_ms, vendor: null, naming_contexts: [], error}; only an invalid configuration throws an error

Parameters

    config:   The connection as a JSON object: url, bind_dn, password or password_env, start_tls, timeout_ms, trust_all, base_dn, referrals, allow_plain - String - required
admin
ldap test "{\"url\": \"ldap://localhost:21389\", \"base_dn\": \"dc=example,dc=org\"}"
mentdb
{"ok": true, "latency_ms": 0, "vendor": "Ping Identity Corporation", "vendor_version": "UnboundID LDAP SDK for Java 7.0.2", "naming_contexts": ["dc=example,dc=org"], "default_naming_context": null, "tls": false}
Result of the UnboundID in-memory test server: LDAPS with a service account
admin
ldap test "{\"url\": \"ldaps://localhost:21636\", \"trust_all\": true, \"bind_dn\": \"cn=svc\", \"password\": \"svcpw\"}"
mentdb
{"ok": true, "latency_ms": 6, "vendor": "Ping Identity Corporation", "vendor_version": "UnboundID LDAP SDK for Java 7.0.2", "naming_contexts": ["dc=example,dc=org"], "default_naming_context": null, "tls": true}
Result of the UnboundID in-memory test server: a certificate which is not trusted
admin
ldap test "{\"url\": \"ldaps://localhost:21636\"}"
mentdb
{"ok": false, "latency_ms": 9, "vendor": null, "naming_contexts": [], "error": "the TLS connection to localhost:21636 failed (untrusted certificate, host name mismatch, or no TLS on this port)"}
Result of the UnboundID in-memory test server: a port where nothing listens
admin
ldap test "{\"url\": \"ldap://localhost:21399\"}"
mentdb
{"ok": false, "latency_ms": 0, "vendor": null, "naming_contexts": [], "error": "the LDAP server localhost:21399 cannot be reached"}

ldap escape_filter <text>


Description

    Escape a text for an LDAP filter (RFC 4515): * ( ) \ and NUL become \2a \28 \29 \5c \00, the non-ASCII characters are left untouched. No connection

Parameters

    text:   The text - String - required
admin
ldap escape_filter "*)(uid=*"
mentdb
\2a\29\28uid=\2a
Non-ASCII characters stay
admin
ldap escape_filter "Éloïse (Paris)"
mentdb
Éloïse \28Paris\29

ldap escape_dn <text>


Description

    Escape a text for a value of a DN (RFC 4514): a space or # at the start, a space at the end, , + " \ < > ; = get a backslash, NUL becomes \00. No connection

Parameters

    text:   The text - String - required
admin
ldap escape_dn "Doe, John"
mentdb
Doe\, John
A space and a # at the start, a space at the end
admin
ldap escape_dn "#a b "
mentdb
\#a b\
An attempt to add a part to the DN
admin
ldap escape_dn "x,ou=admin"
mentdb
x\,ou\=admin