docs: clarify scope of MAX_LOGIN_ATTEMPTS and document brute-force protection for LDAP

The "Avoiding a bruteforce attack" section in login.rst implied that
MAX_LOGIN_ATTEMPTS protected all logins; in fact it only applies to the
INTERNAL authentication source (the /authenticate/login view filters by
auth_source=INTERNAL). Operators using LDAP / OAUTH2 / KERBEROS /
WEBSERVER got no signal that brute-force protection lives at a different
layer.

Adds:

  - login.rst: the bruteforce section now states that MAX_LOGIN_ATTEMPTS
    is INTERNAL-only and points operators of external sources to the
    upstream identity provider's lockout policy and to the reverse proxy
    for IP-based throttling.
  - ldap.rst: a new "Brute-force protection" section calling out that
    LDAP credential lockout is the directory's responsibility (ppolicy /
    AD account-lockout GPO) and that request rate-limiting belongs on
    the proxy. Cross-references the login-page section.

No code change. Closes the documentation gap that surfaced during the
analysis of the #9904 lockout-bypass fix without inheriting the
maintenance burden of duplicating directory lockout in pgAdmin.
This commit is contained in:
Ashesh Vashi
2026-05-05 15:03:00 +05:30
parent 32d194691e
commit 9923eefcab
2 changed files with 40 additions and 3 deletions
+25
View File
@@ -110,3 +110,28 @@ There are 3 ways to configure LDAP:
"LDAP_BIND_PASSWORD", "Password for simple bind.
Specify the value if you have set the LDAP_BIND_USER parameter."
Brute-force protection
**********************
pgAdmin's built-in account-lockout setting (``MAX_LOGIN_ATTEMPTS``) applies
only to accounts using the ``INTERNAL`` authentication source. It does
**not** rate-limit or lock LDAP-authenticated logins.
When LDAP authentication is enabled, brute-force protection for LDAP
credentials is the responsibility of:
- **The directory.** Configure account-lockout policy on the LDAP server
itself (for example, OpenLDAP's ``ppolicy`` overlay, Active Directory's
account-lockout GPO, or the equivalent on FreeIPA / 389 Directory
Server). The directory is the credential authority and is the correct
place to enforce per-account lockout.
- **The reverse proxy or WAF in front of pgAdmin.** Configure
request-rate limiting on the login endpoint (for example, ``limit_req``
in nginx, ``stick-table`` rules in HAProxy, or the equivalent in your
WAF) to bound login-attempt volume per source IP. This is independent
of pgAdmin and protects against attackers who would otherwise reach the
LDAP server through pgAdmin.
See :ref:`Avoiding a bruteforce attack <login>` for the equivalent note
on the login page.
+15 -3
View File
@@ -60,6 +60,18 @@ asking you to contact the LDAP administrator to recover your LDAP password.
Avoiding a bruteforce attack
****************************
You have the possibility to lock an account by setting ``MAX_LOGIN_ATTEMPTS``
once it has reached the maximum number of login attempts.
You can disable this feature by setting the value to zero.
For accounts using the ``INTERNAL`` authentication source, pgAdmin locks
the account after ``MAX_LOGIN_ATTEMPTS`` consecutive failed logins. The
default is 3; set it to zero to disable.
For accounts authenticated against an external identity provider
(``LDAP``, ``OAUTH2``, ``KERBEROS``, ``WEBSERVER``), brute-force protection
is **not** handled by pgAdmin and ``MAX_LOGIN_ATTEMPTS`` does not apply.
Operators using these sources should:
- Configure account-lockout policy on the upstream provider (for example,
Active Directory's account-lockout GPO, OpenLDAP's ``ppolicy`` overlay,
or the OAuth2 provider's rate limits).
- Configure request rate-limiting (for example, ``limit_req`` in nginx)
on the reverse proxy in front of pgAdmin to bound login-attempt volume
per source IP.