Authn.tech
Home
  • SAML 2.0
  • OAuth 2.0
  • OIDC
  • WebAuthn / Passkey
  • MFA / TOTP
  • LDAP
  • All Tools
  • JWT Decode
  • JWT Sign
  • JWK Gen
  • JWK → PEM
  • PEM → JWK
  • PKCE Gen
  • OIDC Discovery
  • TOTP
  • WebAuthn
  • SAML Codec
  • SAML Metadata
  • SAML Response
  • X.509 Cert
  • PEM Inspect
  • Base64URL
  • LDAP Filter
  • Overview & Roles
  • OIDC Mock
  • SAML Mock
  • Mail Server
  • LDAP Directory
  • OIDC Login Demo
  • SAML Login Demo
  • 简体中文
  • English
  • Deutsch
GitHub
Home
  • SAML 2.0
  • OAuth 2.0
  • OIDC
  • WebAuthn / Passkey
  • MFA / TOTP
  • LDAP
  • All Tools
  • JWT Decode
  • JWT Sign
  • JWK Gen
  • JWK → PEM
  • PEM → JWK
  • PKCE Gen
  • OIDC Discovery
  • TOTP
  • WebAuthn
  • SAML Codec
  • SAML Metadata
  • SAML Response
  • X.509 Cert
  • PEM Inspect
  • Base64URL
  • LDAP Filter
  • Overview & Roles
  • OIDC Mock
  • SAML Mock
  • Mail Server
  • LDAP Directory
  • OIDC Login Demo
  • SAML Login Demo
  • 简体中文
  • English
  • Deutsch
GitHub
  • LDAP

    • LDAP Overview
    • Core Concepts
    • Typical Flows
    • Parameters and Syntax Reference

LDAP Typical Flows

Search: bind → search → result

Client                         LDAP Server
  │  1. bind(DN, password / anonymous)   │
  │ ───────────────────────────────▶│  validate credentials
  │  bindResponse: success           │
  │ ◀───────────────────────────────│
  │  2. searchRequest                │
  │     base, scope, filter, attrs   │
  │ ───────────────────────────────▶│  traverse entries in scope, match by filter
  │  searchResultEntry * N           │
  │ ◀───────────────────────────────│  (return one entry per match)
  │  searchResultDone: success       │
  │ ◀───────────────────────────────│
  │  3. unbind                       │
  │ ───────────────────────────────▶│

Demonstrate the same process with ldapsearch:

ldapsearch -H ldaps://ldap.example.com \
  -D "cn=svc-reader,ou=apps,dc=example,dc=com" -w '****' \
  -b "ou=people,dc=example,dc=com" -s sub \
  "(&(objectClass=person)([email protected]))" cn mail

User Authentication: Two Approaches

1) Direct bind (simple bind)

The application directly uses the user's DN + the password entered by the user to bind; success means authentication succeeds:

  1. If the user DN pattern is known (e.g., uid=<input>,ou=people,dc=example,dc=com), construct the DN directly;
  2. bind(userDN, password);
  3. Success = password is correct; failure (invalidCredentials) = deny login.

Simple, but requires the application to be able to derive the DN from the username.

2) search + bind (most common)

The username may not equal the RDN (login might be via mail or sAMAccountName), so:

  1. The application first binds with a service account (read-only permissions);
  2. search the user entry by login name to get its true DN, for example (|(uid=<input>)(mail=<input>));
  3. Bind again with the found DN + user password to verify the password;
  4. (Optional) search / read memberOf again to check group membership for authorization.
Application ──bind(service account)──▶ LDAP
Application ──search(&(objectClass=person)(mail=user input))──▶ LDAP  → get userDN
Application ──bind(userDN, user password)──▶ LDAP  → success/failure
Application ──search(memberOf / group member)──▶ LDAP  → check authorization

Connection with Federated Login

LDAP/AD commonly serves as the backend directory for an IdP in enterprises:

User ──SAML/OIDC──▶ IdP(Keycloak/ADFS) ──LDAP bind+search──▶ AD/LDAP
                         │
                         └── retrieve attributes/groups from directory → map into SAML assertion / OIDC claims

That is, the front end speaks SAML / OIDC, but behind the scenes LDAP bind/search still performs authentication and data retrieval.

Want to try search and filters? Use the Filter Builder on the Mock LDAP example directory.

Last updated: 7/6/26, 8:43 AM
Contributors: linux, Claude Opus 4.8
Prev
Core Concepts
Next
Parameters and Syntax Reference