Summary
Admin accounts are subject to the same account lockout policy as regular users. After 5 failed login attempts (default max_failed_login_attempts), the admin account is locked for 30 minutes (account_lockout_duration_minutes). The protect_all_admins setting only prevents admin demotion/deactivation — it does not exempt admins from login lockout.
This creates a denial-of-service vector: an attacker (or automated testing) can intentionally lock out all admin accounts by sending bad passwords.
Steps to Reproduce
- Set
protect_all_admins=true (default)
- Attempt to log in as
admin@example.com with a wrong password 5 times
- Try to log in with the correct password
- Result: "Invalid email or password" — account is locked for 30 minutes
Root Cause
authenticate_user() in email_auth_service.py calls user.is_account_locked() and user.increment_failed_attempts() with no is_admin check:
# email_auth_service.py:453 — no admin exemption
if user.is_account_locked():
failure_reason = "Account is locked"
return None
# email_auth_service.py:466 — no admin exemption
is_locked = user.increment_failed_attempts(max_attempts, lockout_duration)
The protect_all_admins guard only exists in update_user() (line 1050-1055) to prevent demotion/deactivation, not in the authentication flow.
Expected Behavior
When protect_all_admins=true, admin accounts should not be fully locked out. Options:
- Exempt admins from hard lockout (still log/alert on brute-force)
- Progressive delay instead of lockout for admin accounts (exponential backoff)
- Separate
admin_lockout_exempt config toggle
Affected Components
mcpgateway/services/email_auth_service.py — authenticate_user()
mcpgateway/db.py — EmailUser.is_account_locked(), increment_failed_attempts()
mcpgateway/config.py — missing admin lockout exemption config
Summary
Admin accounts are subject to the same account lockout policy as regular users. After 5 failed login attempts (default
max_failed_login_attempts), the admin account is locked for 30 minutes (account_lockout_duration_minutes). Theprotect_all_adminssetting only prevents admin demotion/deactivation — it does not exempt admins from login lockout.This creates a denial-of-service vector: an attacker (or automated testing) can intentionally lock out all admin accounts by sending bad passwords.
Steps to Reproduce
protect_all_admins=true(default)admin@example.comwith a wrong password 5 timesRoot Cause
authenticate_user()inemail_auth_service.pycallsuser.is_account_locked()anduser.increment_failed_attempts()with nois_admincheck:The
protect_all_adminsguard only exists inupdate_user()(line 1050-1055) to prevent demotion/deactivation, not in the authentication flow.Expected Behavior
When
protect_all_admins=true, admin accounts should not be fully locked out. Options:admin_lockout_exemptconfig toggleAffected Components
mcpgateway/services/email_auth_service.py—authenticate_user()mcpgateway/db.py—EmailUser.is_account_locked(),increment_failed_attempts()mcpgateway/config.py— missing admin lockout exemption config