Stop the built-in Administrator account on your Frappe site from logging in with an email and password β one checkbox, enforced server-side, lockout-proof.
The built-in Administrator account is the most valuable default credential on every Frappe installation. This app removes it from the email-password attack surface entirely.
- Features
- Requirements
- Installation
- Usage
- Lockout protection
- How It Works
- Architecture
- Tests
- Version support
- Credits
- License
- β
Blocks
Administratoremail/password login when enabled - β
Pure server-side β
on_loginsession hook, zero client-side JS, zero DOM hacks - β Lockout-proof β refuses to enable if no other enabled System Manager exists
- β Install-time custom field with anchor fallback; patch ships upgrades from v15
- β
Existing
Administratorsessions are never interrupted - β Works with Frappe v16
- Frappe v16 (bench)
bench get-app https://github.com/iamimmanuelraj/block_administrator --branch version-16
bench --site your-site.com install-app block_administratorUsing the
developbranch? Same code βdevelopis the v16 line with nightly CI.
- Install the app (above).
- Go to System Settings β Login.
- Check Block Administrator Login β it sits right below Disable Username/Password Login, or on the Advanced tab.
- Save. The
Administratoraccount can no longer log in with an email and password. Unchecking re-enables login immediately.
Current logged-in sessions of the Administrator account are not affected by this setting β only future logins are blocked.
Why block the administrator account?
The `Administrator` account has full system access. When email-password authentication is enabled, it becomes a high-value target for brute-force attacks. This app mitigates the risk by preventing direct login to the account β without disabling email-password login for everyone else.
You cannot lock yourself out. Enabling the block is rejected unless at least one other enabled user holds the System Manager role, so a recovery path always exists.
Cannot block Administrator login as no other enabled user has the System Manager role. You would lose all admin access.
Disabling the block (or saving unrelated settings) is always allowed.
flowchart TD
A[Login with email + password] --> B[Frappe verifies credentials]
B --> C{on_login hook<br/>validate_login}
C --> D{user is Administrator?}
D -->|No| E[Session created β normal flow]
D -->|Yes| F{block_administrator_login<br/>enabled?}
F -->|No| E
F -->|Yes| G[AuthenticationError β<br/>login rejected, no session]
H[Save System Settings] --> I{doc_events validate<br/>validate_system_settings}
I --> J{enabling the block?}
J -->|No| K[Allowed]
J -->|Yes| L{another enabled user<br/>with System Manager?}
L -->|Yes| K
L -->|No| M[ValidationError β<br/>lockout prevented]
The on_login hook runs after credentials are verified but before the session is created β a blocked login fails cleanly with an AuthenticationError and leaves no session behind.
The v16 line is a full server-side rewrite of the v15 approach. No DocType, no client script β everything lives in four small modules:
| Module | Responsibility |
|---|---|
install.py |
Creates the block_administrator_login Check custom field on System Settings at install. insert_after resolves against live metadata (disable_user_pass_login β login_methods_section β deny_multiple_sessions β session_expiry), falling back to append so it never breaks on future Frappe changes |
auth/__init__.py |
validate_login(login_manager) β the on_login hook. Rejects Administrator logins when the setting is on; bails out gracefully if the custom field hasn't synced yet |
validations.py |
validate_system_settings(doc) β the doc_events guard that prevents enabling the block when no other enabled System Manager exists |
patches/v1_0_0/ |
Migration patch that adds the custom field to existing installs (e.g. upgrading from v15) |
| Hook | Type | Purpose |
|---|---|---|
on_login |
Session hook | Blocks Administrator login post-verification, pre-session |
doc_events β System Settings.validate |
Document event | Lockout guard on enable |
after_install |
Install hook | Creates the custom field |
Why this design? The v15 approach injected the checkbox into the System Settings form with client-side JS and stored state in a singleton DocType β fragile against Frappe UI changes and bypassable at the framework layer. The v16 rewrite is declarative: a real custom field, a session-level hook, and server-side validation only.
block_administrator/tests/test_block_administrator.py β integration tests covering:
test_blocks_administrator_login_when_enabledtest_allows_administrator_login_when_disabledtest_allows_other_users_when_enabledtest_rejects_enabling_when_no_other_userstest_rejects_enabling_when_no_other_system_managertest_allows_enabling_when_other_system_manager_existstest_allows_disabling_always
bench --site your-site.com run-tests --app block_administrator| Branch | Frappe | Mechanism | Status |
|---|---|---|---|
version-16 |
v16 | Server-side custom field + on_login hook |
Current |
develop |
v16 | Same + nightly CI | Current |
version-15 |
v15 | Injected checkbox + singleton DocType + auth hook | Legacy |
Migrating from v15:
version-15/version-16are branches of the same app β do not uninstall. In bench, switch the app checkout to theversion-16branch, then runbench --site your-site.com migrate. Thev1_0_0patch creates the custom field, carries over the oldblock_administrator_loginvalue from theBlock Administratorsingleton, and removes the orphaned Module Def left behind by the old module.
Built on the Frappe Framework, the open-source, metadata-driven framework created by Frappe Technologies.
GPLv3 β see the LICENSE file for the full text.