---
title: Learn LDAP
description: Lightweight Directory Access Protocol (LDAP) is a standard internet protocol. The following examples show you how to use bundled DS command-line tools to send LDAP requests.
component: pingds
version: 8.1
page_id: pingds:getting-started:ldap
canonical_url: https://docs.pingidentity.com/pingds/8.1/getting-started/ldap.html
revdate: 2025-10-22T14:42:39Z
keywords: ["Evaluation", "LDAP"]
section_ids:
  search-ldap: Search
  modify-ldap: Modify
  add-ldap: Add
  delete-ldap: Delete
---

# Learn LDAP

Lightweight Directory Access Protocol (LDAP) *(tooltip: \<div class="paragraph">
\<p>An open, cross-platform protocol used for interacting with directory services.\</p>
\</div>)* is a standard internet protocol. The following examples show you how to use bundled DS command-line tools to send LDAP requests.

Before you try the examples, set up a server, as described in [Install DS](install.html). Make sure you added the command-line tools to your PATH:

* Bash

* PowerShell

* Zsh

```console
$ export PATH=/path/to/opendj/bin:${PATH}
```

```powershell
$env:PATH += ";C:\path\to\opendj\bat"
```

```console
$ export PATH=/path/to/opendj/bin:${PATH}
```

## Search

Searching the directory is like looking for someone's phone number when all you know is their name. You use the value of an attribute you know—​in this case, their name—​to find their profile. Their profile—​in LDAP, their entry—​has other attributes of interest like their phone number or email address.

When looking up a person's entry by their name, more information helps narrow down your search. If two people with the same name live in Los Angeles and New York, you need to know where they live to choose the right person. In an LDAP directory, you need to know at least the base distinguished name (DN) *(tooltip: \<div class="paragraph">
\<p>A name uniquely identifying an object within the hierarchy of a directory tree.\</p>
\</div>)* for the search.

For this example, assume you know a user's full name, `Babs Jensen`, and that Babs Jensen's entry is under the base DN `dc=example,dc=com`. You want to look up Babs Jensen's email and office location. The following command sends an appropriate LDAP search request to the server you installed:

* Bash

* PowerShell

* Zsh

```console
$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --trustStorePath /path/to/opendj/config/keystore \
 --trustStoreType PKCS12 \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=bjensen,ou=People,dc=example,dc=com \
 --bindPassword hifalutin \
 --baseDn dc=example,dc=com \
 "(cn=Babs Jensen)" \
 cn mail street l
```

> **Collapse: Show output**
>
> ```
> dn: uid=bjensen,ou=People,dc=example,dc=com
> cn: Barbara Jensen
> cn: Babs Jensen
> l: San Francisco
> mail: bjensen@example.com
> street: 201 Mission Street Suite 2900
> ```

```powershell
ldapsearch.bat `
 --hostname localhost `
 --port 1636 `
 --useSsl `
 --trustStorePath C:\path\to\opendj\config\
 --trustStoreType PKCS12 \keystore `
 --trustStorePassword:file C:\path\to\opendj\config\keystore.pin `
 --bindDN uid=bjensen,ou=People,dc=example,dc=com `
 --bindPassword hifalutin `
 --baseDn dc=example,dc=com `
 "(cn=Babs Jensen)" `
 cn mail street l
```

> **Collapse: Show output**
>
> ```
> dn: uid=bjensen,ou=People,dc=example,dc=com
> cn: Barbara Jensen
> cn: Babs Jensen
> l: San Francisco
> mail: bjensen@example.com
> street: 201 Mission Street Suite 2900
> ```

```console
$ ldapsearch \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --trustStorePath /path/to/opendj/config/keystore \
 --trustStoreType PKCS12 \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDN uid=bjensen,ou=People,dc=example,dc=com \
 --bindPassword hifalutin \
 --baseDn dc=example,dc=com \
 "(cn=Babs Jensen)" \
 cn mail street l
```

> **Collapse: Show output**
>
> ```
> dn: uid=bjensen,ou=People,dc=example,dc=com
> cn: Barbara Jensen
> cn: Babs Jensen
> l: San Francisco
> mail: bjensen@example.com
> street: 201 Mission Street Suite 2900
> ```

> **Collapse: More about the search example**
>
> Notice the following characteristics of the search:
>
> * The command makes a secure connection to the server using LDAPS *(tooltip: \<div class="paragraph">
>   \<p>LDAP over TLS.\</p>
>   \</div>)*.
>
>   The command relies on the server's truststore to trust the CA certificate used to sign the server certificate.
>
> * The base DN option, `--baseDn dc=example,dc=com`, tells the server where to look for Babs Jensen's entry. Servers can hold data for multiple base DNs, so this is important information.
>
>   It is possible to restrict the scope of the search, but the default is to search the entire subtree under the base DN.
>
> * The command uses a LDAP search filter (filter) *(tooltip: \<div class="paragraph">
>   \<p>An expression the server uses to find entries matching a search request.\</p>
>   \</div>)*, `"(cn=Babs Jensen)"`, which tells the server, "Find entries whose `cn` attribute exactly matches the string `Babs Jensen` without regard to case."
>
>   The `cn` (`commonName`) attribute is a standard attribute for full names.
>
>   Internally, the directory server has an equality index for the `cn` attribute. The directory uses the index to quickly find matches for `babs jensen`. The default behavior in LDAP is to ignore case, so `"(cn=Babs Jensen)"`, `"(cn=babs jensen)"`, and `"(CN=BABS JENSEN)"` are equivalent.
>
>   If more than one entry matches the filter, the server returns multiple entries.
>
> * The filter is followed by a list of attributes *(tooltip: \<div class="paragraph">
>   \<p>A property of a directory entry, stored as one or more key-value pairs.\</p>
>   \</div>)*, `cn mail street l`. This tells the server to return only the specified attributes in the search result entries. By default, if you do not specify the attributes to return, the server returns all the user attributes that you have the right to read.
>
> * The result shows attributes from a single entry. Notice that an LDAP entry, represented here in the standard LDIF format, has a flat structure with no nesting.
>
>   The DN that uniquely identifies the entry is `uid=bjensen,ou=People,dc=example,dc=com`. Multiple entries can have the same attribute values, but each must have a unique DN. This is the same as saying that the leading relative distinguished name (RDN) *(tooltip: \<div class="paragraph">
>   \<p>The initial portion of a DN distinguishing the entry from all others at the same level.\</p>
>   \</div>)* value must be unique at this level in the hierarchy. Only one entry directly under `ou=People,dc=example,dc=com` has the RDN `uid=bjensen`.
>
>   The `mail`, `street`, `l` (location), and `uid` attributes are all standard LDAP attributes like `cn`.

For additional examples, refer to [LDAP search](../ldap-guide/search-ldap.html).

## Modify

You installed the server with the `ds-evaluation` profile. That profile grants access to search Example.com data without authenticating to the directory. When modifying directory data, however, you must authenticate first. LDAP servers must know who you are to determine what you have access to.

In the following example Babs Jensen modifies the description on her own entry:

* Bash

* PowerShell

* Zsh

```console
$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --trustStorePath /path/to/opendj/config/keystore \
 --trustStoreType PKCS12 \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDn uid=bjensen,ou=People,dc=example,dc=com \
 --bindPassword hifalutin <<EOF
dn: uid=bjensen,ou=People,dc=example,dc=com
changetype: modify
replace: description
description: New description
EOF
```

> **Collapse: Show output**
>
> ```
> # MODIFY operation successful for DN uid=bjensen,ou=People,dc=example,dc=com
> ```

```powershell
New-Item -Path . -Name "description.ldif" -ItemType "file" -Value @"
dn: uid=bjensen,ou=People,dc=example,dc=com
changetype: modify
replace: description
description: New description
"@
ldapmodify.bat `
 --hostname localhost `
 --port 1636 `
 --useSsl `
 --trustStorePath C:\path\to\opendj\config\
 --trustStoreType PKCS12 \keystore `
 --trustStorePassword:file C:\path\to\opendj\config\keystore.pin `
 --bindDn uid=bjensen,ou=People,dc=example,dc=com `
 --bindPassword hifalutin `
 description.ldif
```

> **Collapse: Show output**
>
> ```
> # MODIFY operation successful for DN uid=bjensen,ou=People,dc=example,dc=com
> ```

```console
$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --trustStorePath /path/to/opendj/config/keystore \
 --trustStoreType PKCS12 \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDn uid=bjensen,ou=People,dc=example,dc=com \
 --bindPassword hifalutin <<EOF
dn: uid=bjensen,ou=People,dc=example,dc=com
changetype: modify
replace: description
description: New description
EOF
```

> **Collapse: Show output**
>
> ```
> # MODIFY operation successful for DN uid=bjensen,ou=People,dc=example,dc=com
> ```

> **Collapse: More about the modify example**
>
> * Babs Jensen's authentication credentials are provided with the `--bindDn` and `--bindPassword` options. Notice that the user identifier is Babs Jensen's DN.
>
>   Authentication operations bind an LDAP identity to a connection. In LDAP, a client application connects to the server, then binds an identity to the connection. An LDAP client application keeps its connection open until it finishes performing its operations. The server uses the identity bound to the connection to make authorization *(tooltip: \<div class="paragraph">
>   \<p>The act of determining whether to grant or deny a user access to a resource.\</p>
>   \</div>)* decisions for subsequent operations, such as search and modify requests.
>
>   If no credentials are provided, then the identity for the connection is that of an anonymous user. As a directory administrator, you can configure access controls for anonymous users just as you configure access controls for other users.
>
>   A simple bind *(tooltip: \<div class="paragraph">
>   \<p>Bind with a user's entry DN and password.\</p>
>   \</div>)* involving a DN and a password is just one of several supported authentication mechanisms. The documentation frequently shows simple binds in examples because this kind of authentication is so familiar. Alternatives include authenticating with a digital certificate, or using Kerberos.
>
> * The modification is expressed in standard LDAP Data Interchange Format (LDIF).
>
>   The LDIF specifies the DN of the target entry to modify. It then indicates that the change to perform is an LDAP modify, and that the value `New description` is to replace existing values of the `description` attribute.
>
> * Notice that the result is a comment indicating success. The command's return code—​0, but not shown in the example—​also indicates success.
>
>   The scripts and applications that you write should use and trust LDAP return codes.

For additional examples, refer to [LDAP updates](../ldap-guide/write-ldap.html) and [Passwords and accounts](../ldap-guide/passwords-and-accounts.html).

## Add

Authorized users can modify attributes, and can also add and delete directory entries.

The following example adds a new user entry to the directory:

* Bash

* PowerShell

* Zsh

```console
$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --trustStorePath /path/to/opendj/config/keystore \
 --trustStoreType PKCS12 \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDn uid=admin \
 --bindPassword password <<EOF
dn: uid=newuser,ou=People,dc=example,dc=com
uid: newuser
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
cn: New User
sn: User
ou: People
mail: newuser@example.com
userPassword: chngthspwd
EOF
```

> **Collapse: Show output**
>
> ```
> # ADD operation successful for DN uid=newuser,ou=People,dc=example,dc=com
> ```

```powershell
New-Item -Path . -Name "user.ldif" -ItemType "file" -Value @"
dn: uid=newuser,ou=People,dc=example,dc=com
uid: newuser
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
cn: New User
sn: User
ou: People
mail: newuser@example.com
userPassword: chngthspwd
"@
ldapmodify.bat `
 --hostname localhost `
 --port 1636 `
 --useSsl `
 --trustStorePath C:\path\to\opendj\config\
 --trustStoreType PKCS12 \keystore `
 --trustStorePassword:file C:\path\to\opendj\config\keystore.pin `
 --bindDn uid=admin `
 --bindPassword password `
 user.ldif
```

> **Collapse: Show output**
>
> ```
> # ADD operation successful for DN uid=newuser,ou=People,dc=example,dc=com
> ```

```console
$ ldapmodify \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --trustStorePath /path/to/opendj/config/keystore \
 --trustStoreType PKCS12 \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDn uid=admin \
 --bindPassword password <<EOF
dn: uid=newuser,ou=People,dc=example,dc=com
uid: newuser
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
cn: New User
sn: User
ou: People
mail: newuser@example.com
userPassword: chngthspwd
EOF
```

> **Collapse: Show output**
>
> ```
> # ADD operation successful for DN uid=newuser,ou=People,dc=example,dc=com
> ```

> **Collapse: More about the add example**
>
> * The bind DN for the user requesting the add is `uid=admin`. It is also possible to authorize regular users to add entries.
>
> * The entry to add is expressed in standard LDIF.

For additional examples, refer to [LDAP updates](../ldap-guide/write-ldap.html).

## Delete

The following example deletes the user added in [Add](#add-ldap):

* Bash

* PowerShell

* Zsh

```console
$ ldapdelete \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --trustStorePath /path/to/opendj/config/keystore \
 --trustStoreType PKCS12 \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDn uid=admin \
 --bindPassword password \
 uid=newuser,ou=People,dc=example,dc=com
```

> **Collapse: Show output**
>
> ```
> # DELETE operation successful for DN uid=newuser,ou=People,dc=example,dc=com
> ```

```powershell
ldapdelete.bat `
 --hostname localhost `
 --port 1636 `
 --useSsl `
 --trustStorePath C:\path\to\opendj\config\
 --trustStoreType PKCS12 \keystore `
 --trustStorePassword:file C:\path\to\opendj\config\keystore.pin `
 --bindDn uid=admin `
 --bindPassword password `
 uid=newuser,ou=People,dc=example,dc=com
```

> **Collapse: Show output**
>
> ```
> # DELETE operation successful for DN uid=newuser,ou=People,dc=example,dc=com
> ```

```console
$ ldapdelete \
 --hostname localhost \
 --port 1636 \
 --useSsl \
 --trustStorePath /path/to/opendj/config/keystore \
 --trustStoreType PKCS12 \
 --trustStorePassword:file /path/to/opendj/config/keystore.pin \
 --bindDn uid=admin \
 --bindPassword password \
 uid=newuser,ou=People,dc=example,dc=com
```

> **Collapse: Show output**
>
> ```
> # DELETE operation successful for DN uid=newuser,ou=People,dc=example,dc=com
> ```

Notice that the `ldapdelete` command specifies the entry to delete by its DN.

For additional examples, refer to [LDAP updates](../ldap-guide/write-ldap.html).
