How to Implement Custom Security Managers Extending Flask-AppBuilder in Apache Superset
You can extend Apache Superset's authentication and authorization layer by subclassing SupersetSecurityManager, registering custom permissions via add_permission_view_menu, and pointing the CUSTOM_SECURITY_MANAGER configuration key to your implementation class.
Apache Superset leverages Flask-AppBuilder (FAB) for its security foundation, handling everything from user authentication to granular role-based access control. When you need to implement custom security managers extending Flask-AppBuilder to integrate external identity providers, modify role creation logic, or add domain-specific permissions, you must inherit from Superset's base security manager and configure the application to load your custom class during startup.
Understanding the Base Security Architecture
The core security logic resides in superset/security/manager.py, where SupersetSecurityManager extends FAB's base SecurityManager. This class defines the permission model that governs access to Superset's features:
- Model view whitelists (
READ_ONLY_MODEL_VIEWS,ADMIN_ONLY_VIEW_MENUS) control which UI views each role can access - Permission sets (
READ_ONLY_PERMISSION,ADMIN_ONLY_PERMISSIONS,SQLLAB_ONLY_PERMISSIONS) map FAB actions (can_read,can_write, etc.) to Superset resources - Helper methods for guest token handling, row-level security (RLS), and SQL Lab permissions
Source: superset/security/manager.py – class definition
Where Superset Loads the Custom Manager
During application initialization, Superset validates and loads your custom security manager in superset/initialization/__init__.py (lines 824-835):
# superset/initialization/__init__.py
custom_sm = self.config["CUSTOM_SECURITY_MANAGER"] or SupersetSecurityManager
if not issubclass(custom_sm, SupersetSecurityManager):
raise Exception("CUSTOM_SECURITY_MANAGER must inherit SupersetSecurityManager")
appbuilder.security_manager_class = custom_sm
This validation ensures that any class referenced by CUSTOM_SECURITY_MANAGER must inherit from SupersetSecurityManager. If your class fails this check, Superset raises an exception during startup.
Step-by-Step Implementation Guide
1. Create a Subclass of SupersetSecurityManager
Create a new Python module (for example, my_security_manager.py) that imports and extends the base class:
from superset.security.manager import SupersetSecurityManager
class CustomSecurityManager(SupersetSecurityManager):
"""Your custom security logic extends the base implementation."""
pass
2. Override init_app to Register Custom Permissions
The init_app method runs once after Flask application creation, making it the ideal hook for registering new permissions and roles. Use add_permission_view_menu to create global permissions and add_permission_role to assign them to specific roles:
def init_app(self, app):
# Always call the parent implementation first
super().init_app(app)
# Register a new permission on a custom resource
self.add_permission_view_menu("can_fly", "Airplane")
# Grant the permission to the Alpha role
alpha_role = self.find_role("Alpha")
if alpha_role:
self.add_permission_role(alpha_role, "can_fly", "Airplane")
3. Configure CUSTOM_SECURITY_MANAGER in superset_config.py
Expose your class to Superset by adding the module path to your configuration file:
# superset_config.py
CUSTOM_SECURITY_MANAGER = "my_package.my_security_manager.CustomSecurityManager"
The string must be a fully qualified Python import path (module + class name) that Python can import at runtime.
Complete Working Example
Here is a production-ready implementation that adds a custom permission and assigns it to the Alpha role:
# my_package/my_security_manager.py
from superset.security.manager import SupersetSecurityManager
class CustomSecurityManager(SupersetSecurityManager):
"""
Example custom security manager that adds a ``can_fly`` permission
and grants it to the ``Alpha`` role.
"""
def init_app(self, app):
# Initialize base FAB security features
super().init_app(app)
# Register a new permission-view menu combination
self.add_permission_view_menu("can_fly", "Airplane")
# Assign the permission to an existing role
alpha_role = self.find_role("Alpha")
if alpha_role:
self.add_permission_role(alpha_role, "can_fly", "Airplane")
Key implementation details:
- Inheritance from
SupersetSecurityManagerpreserves all default authentication and authorization behavior - Super call in
init_appensures critical security hooks (guest token handling, database initialization) remain active - Permission registration via
add_permission_view_menumakes the permission available throughout the application - Role assignment through
add_permission_roleimmediately grants capabilities to users with that role
Advanced Customization Patterns
You can override specific methods in your custom security manager to handle specialized use cases:
- External SSO integration (SAML, OIDC, LDAP): Override
auth_user_oauthorauth_user_ldapto map external attributes to Superset roles - Dynamic role assignment: Override
get_user_rolesto compute roles based on request context, JWT claims, or IP addresses - Row-level security enhancements: Extend
get_rls_filtersto inject custom filters per user or group - Audit logging: Override
log_user_actionto push security events to external SIEM systems
All these hooks are defined in superset/security/manager.py and can be customized while maintaining compatibility with FAB's security framework.
Common Pitfalls to Avoid
When implementing custom security managers extending Flask-AppBuilder, watch for these common errors:
- Missing inheritance: If your class does not inherit
SupersetSecurityManager, the initialization check insuperset/initialization/__init__.pyraises an exception - Skipping super().init_app(app): Omitting the parent call disables built-in security features including guest token handling and permission synchronization
- Permission name collisions: FAB treats permission strings case-sensitively; avoid shadowing existing permissions like
can_writeorcan_read - Import path errors: The
CUSTOM_SECURITY_MANAGERstring must be a valid Python import path; typos result inImportErrorat startup - Database synchronization: New permissions require the Superset metadata database to be initialized; ensure
superset db upgradehas run before starting the application with new permissions
Summary
- Create a Python class that inherits from
SupersetSecurityManagerinsuperset/security/manager.pyto maintain compatibility with Flask-AppBuilder - Override
init_appto register custom permissions usingadd_permission_view_menuand assign them to roles withadd_permission_role - Configure the fully qualified class path in
CUSTOM_SECURITY_MANAGERinsidesuperset_config.py - Always call
super().init_app(app)to preserve default security initialization logic - Validate inheritance during startup in
superset/initialization/__init__.pyensures your custom manager integrates safely with the security stack
Frequently Asked Questions
What happens if my custom security manager does not inherit from SupersetSecurityManager?
Superset validates the class hierarchy during initialization in superset/initialization/__init__.py (lines 824-835). If your class is not a subclass of SupersetSecurityManager, the application raises an exception immediately at startup with the message "CUSTOM_SECURITY_MANAGER must inherit SupersetSecurityManager".
Can I use a custom security manager to integrate OAuth or SAML authentication?
Yes. Override methods like auth_user_oauth for OAuth providers or auth_user_ldap for LDAP integration. These methods receive the authentication response from Flask-AppBuilder and allow you to map external user attributes to Superset roles before returning a user object.
Where should I place my custom security manager code?
You can place your custom security manager in any Python module that is importable by Superset. Common locations include a security/ directory adjacent to your superset_config.py file, or within an installed Python package. Ensure the module path in CUSTOM_SECURITY_MANAGER matches the actual file location.
How do I verify that my custom permissions were registered correctly?
After starting Superset with your custom manager, query the FAB security tables (ab_permission_view_role, ab_permission_view, ab_permission) in the metadata database to verify your permissions exist. Alternatively, write an integration test that loads a test application instance with CUSTOM_SECURITY_MANAGER set and asserts that security_manager.find_permission_view_menu("can_fly", "Airplane") returns a valid object.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →