Browse docs

Authentication in Active Directory

How to read Active Directory's extended bind error strings to distinguish wrong passwords from disabled, expired, or locked accounts.

On this page

A failed bind against Active Directory returns more detail than the generic LDAP result code covered in Bind and authentication. AD appends an extended error string that tells you specifically why the bind failed — which matters a lot for giving users a useful error message.

Anatomy of an extended error

A typical failed bind against AD looks like this:

text
80090308: LdapErr: DSID-0C090442, comment: AcceptSecurityContext error, data 52e, v3839
  • 80090308 is a Win32 error code.
  • DSID-0C090442 identifies where inside AD's code the error was raised (useful for Microsoft support cases, not usually for your application).
  • data 52e is the part that actually matters — a sub-code telling you the specific reason.
Common data codes
Data codeMeaning
525User not found
52eInvalid credentials (wrong password)
530Not permitted to logon at this time (logon hours restriction)
531Not permitted to logon at this workstation
532Password expired
533Account disabled
701Account expired
773User must reset password before logging on
775Account locked out

Rather than memorizing this table, paste the raw error string into the decoder below — it parses the win32 code, DSID, and data sub-code, and tells you exactly what happened.

Handling this in ldapjs
ts
client.bind(userDn, password, (err) => {
  if (!err) {
    // success
    return;
  }

  const message = err.message ?? "";
  if (message.includes("data 532")) {
    // password expired — prompt for a reset
  } else if (message.includes("data 533")) {
    // account disabled
  } else if (message.includes("data 775")) {
    // account locked out
  } else {
    // generic invalid credentials — don't reveal which case
  }
});

Security

Be deliberate about what you surface to end users. Distinguishing "wrong password" from "account doesn't exist" in a public-facing error message can help an attacker enumerate valid usernames. Reserve the detailed reason for internal logs, and consider showing a generic message externally.

What's next

That completes the Active Directory section. For encrypting these connections and avoiding filter injection in the code shown throughout this guide, continue to Security.