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 SupersetSecurityManager preserves all default authentication and authorization behavior
  • Super call in init_app ensures critical security hooks (guest token handling, database initialization) remain active
  • Permission registration via add_permission_view_menu makes the permission available throughout the application
  • Role assignment through add_permission_role immediately 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_oauth or auth_user_ldap to map external attributes to Superset roles
  • Dynamic role assignment: Override get_user_roles to compute roles based on request context, JWT claims, or IP addresses
  • Row-level security enhancements: Extend get_rls_filters to inject custom filters per user or group
  • Audit logging: Override log_user_action to 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 in superset/initialization/__init__.py raises 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_write or can_read
  • Import path errors: The CUSTOM_SECURITY_MANAGER string must be a valid Python import path; typos result in ImportError at startup
  • Database synchronization: New permissions require the Superset metadata database to be initialized; ensure superset db upgrade has run before starting the application with new permissions

Summary

  • Create a Python class that inherits from SupersetSecurityManager in superset/security/manager.py to maintain compatibility with Flask-AppBuilder
  • Override init_app to register custom permissions using add_permission_view_menu and assign them to roles with add_permission_role
  • Configure the fully qualified class path in CUSTOM_SECURITY_MANAGER inside superset_config.py
  • Always call super().init_app(app) to preserve default security initialization logic
  • Validate inheritance during startup in superset/initialization/__init__.py ensures 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →