CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-flower

Web-based tool for monitoring and administrating Celery clusters with real-time task tracking and worker management.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

authentication.mddocs/

Authentication

Multiple authentication methods including Basic Auth and OAuth2 integration with various providers for securing Flower web interface and API access.

Capabilities

Authentication Functions

def authenticate(pattern, email):
    """
    Check if email matches authentication pattern.
    
    Args:
        pattern (str): Authentication pattern (regex or email list)
        email (str): User email to validate
        
    Returns:
        bool: True if email is authorized
        
    Supports regex patterns and comma-separated email lists.
    """

def validate_auth_option(pattern):
    """
    Validate authentication pattern syntax.
    
    Args:
        pattern (str): Authentication pattern to validate
        
    Returns:
        bool: True if pattern is valid
        
    Validates regex syntax and email format patterns.
    """

OAuth2 Providers

Google OAuth2 Handler

class GoogleAuth2LoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
    """
    Google OAuth2 authentication handler with profile and email scope access.
    """
    
    _OAUTH_SETTINGS_KEY = 'oauth'
    
    async def get(self):
        """
        Handle OAuth2 authentication flow.
        
        Processes both authorization redirect and callback phases:
        - Without code: Redirects to Google OAuth2 authorization
        - With code: Processes callback and authenticates user
        """
    
    async def _on_auth(self, user):
        """
        Process authentication result from Google.
        
        Args:
            user (dict): OAuth2 user data containing access_token
            
        Raises:
            tornado.web.HTTPError: 403 if authentication fails or user unauthorized
            
        Retrieves user email from Google API and validates against auth pattern.
        Sets secure cookie and redirects to requested page on success.
        """

GitHub OAuth2 Handler

class GithubLoginHandler(BaseHandler, tornado.auth.OAuth2Mixin):
    """
    GitHub OAuth2 authentication handler with support for GitHub Enterprise.
    """
    
    _OAUTH_DOMAIN = os.getenv("FLOWER_GITHUB_OAUTH_DOMAIN", "github.com")
    _OAUTH_AUTHORIZE_URL = f'https://{_OAUTH_DOMAIN}/login/oauth/authorize'
    _OAUTH_ACCESS_TOKEN_URL = f'https://{_OAUTH_DOMAIN}/login/oauth/access_token'
    _OAUTH_NO_CALLBACKS = False
    _OAUTH_SETTINGS_KEY = 'oauth'
    
    async def get_authenticated_user(self, redirect_uri, code):
        """
        Exchange authorization code for access token.
        
        Args:
            redirect_uri (str): OAuth2 redirect URI
            code (str): Authorization code from GitHub
            
        Returns:
            dict: Token response containing access_token
            
        Raises:
            tornado.auth.AuthError: If token exchange fails
        """
    
    async def get(self):
        """
        Handle OAuth2 authentication flow for GitHub.
        
        Supports both github.com and GitHub Enterprise instances.
        Uses 'user:email' scope to access verified email addresses.
        """
    
    async def _on_auth(self, user):
        """
        Process authentication result from GitHub.
        
        Args:
            user (dict): OAuth2 user data containing access_token
            
        Raises:
            tornado.web.HTTPError: 403 if no verified emails match auth pattern
            
        Retrieves all verified email addresses and validates against auth pattern.
        Uses first matching verified email for authentication.
        """

GitLab OAuth2 Handler

class GitLabLoginHandler(BaseHandler, tornado.auth.OAuth2Mixin):
    """
    GitLab OAuth2 authentication handler with group-based authorization support.
    """
    
    _OAUTH_GITLAB_DOMAIN = os.getenv("FLOWER_GITLAB_OAUTH_DOMAIN", "gitlab.com")
    _OAUTH_AUTHORIZE_URL = f'https://{_OAUTH_GITLAB_DOMAIN}/oauth/authorize'
    _OAUTH_ACCESS_TOKEN_URL = f'https://{_OAUTH_GITLAB_DOMAIN}/oauth/token'
    _OAUTH_NO_CALLBACKS = False
    
    async def get_authenticated_user(self, redirect_uri, code):
        """
        Exchange authorization code for access token.
        
        Args:
            redirect_uri (str): OAuth2 redirect URI
            code (str): Authorization code from GitLab
            
        Returns:
            dict: Token response containing access_token
            
        Raises:
            tornado.auth.AuthError: If token exchange fails
        """
    
    async def get(self):
        """
        Handle OAuth2 authentication flow for GitLab.
        
        Uses 'read_api' scope to access user information and group memberships.
        Supports both gitlab.com and self-hosted GitLab instances.
        """
    
    async def _on_auth(self, user):
        """
        Process authentication result from GitLab.
        
        Args:
            user (dict): OAuth2 user data containing access_token
            
        Environment Variables:
            FLOWER_GITLAB_AUTH_ALLOWED_GROUPS: Comma-separated list of allowed groups
            FLOWER_GITLAB_MIN_ACCESS_LEVEL: Minimum access level (default: 20)
            
        Raises:
            tornado.web.HTTPError: 403 if user email or group membership unauthorized
            
        Validates both email pattern and group membership if groups are configured.
        """

Okta OAuth2 Handler

class OktaLoginHandler(BaseHandler, tornado.auth.OAuth2Mixin):
    """
    Okta OAuth2 authentication handler with state validation for security.
    """
    
    _OAUTH_NO_CALLBACKS = False
    _OAUTH_SETTINGS_KEY = 'oauth'
    
    @property
    def base_url(self):
        """
        Okta base URL from environment.
        
        Returns:
            str: Base URL from FLOWER_OAUTH2_OKTA_BASE_URL environment variable
        """
    
    @property
    def _OAUTH_AUTHORIZE_URL(self):
        """OAuth2 authorization endpoint URL."""
        return f"{self.base_url}/v1/authorize"
    
    @property
    def _OAUTH_ACCESS_TOKEN_URL(self):
        """OAuth2 token endpoint URL."""
        return f"{self.base_url}/v1/token"
    
    @property
    def _OAUTH_USER_INFO_URL(self):
        """OAuth2 user info endpoint URL."""
        return f"{self.base_url}/v1/userinfo"
    
    async def get_access_token(self, redirect_uri, code):
        """
        Exchange authorization code for access token.
        
        Args:
            redirect_uri (str): OAuth2 redirect URI
            code (str): Authorization code from Okta
            
        Returns:
            dict: Token response containing access_token
            
        Raises:
            tornado.auth.AuthError: If token exchange fails
        """
    
    async def get(self):
        """
        Handle OAuth2 authentication flow for Okta.
        
        Implements state validation for CSRF protection.
        Uses 'openid email' scope for authentication.
        """
    
    async def _on_auth(self, access_token_response):
        """
        Process authentication result from Okta.
        
        Args:
            access_token_response (dict): Token response containing access_token
            
        Raises:
            tornado.web.HTTPError: 403 if email not verified or unauthorized
            
        Retrieves user info from Okta userinfo endpoint and validates email.
        Requires verified email address matching auth pattern.
        """

Login Handler Factory

class LoginHandler(BaseHandler):
    """
    Factory class that instantiates the appropriate OAuth2 handler.
    
    Uses the auth_provider option to determine which handler to create.
    Returns NotFoundErrorHandler if no provider is configured.
    """
    
    def __new__(cls, *args, **kwargs):
        """
        Create appropriate login handler instance.
        
        Returns:
            BaseHandler: OAuth2 provider handler or NotFoundErrorHandler
        """

Configuration Options

Basic Authentication

# Single user
--basic-auth=admin:password

# Multiple users (comma-separated)
--basic-auth=admin:secret,user:pass

# Environment variable
export FLOWER_BASIC_AUTH=admin:secret

Email-based Authentication

# Specific emails
--auth=user@domain.com,admin@company.com

# Domain-based (regex)
--auth=.*@company\.com

# OAuth2 provider with email filtering
--auth=google --auth=.*@company\.com

OAuth2 Configuration

# Google OAuth2
--auth=google
--oauth2-key=your-client-id
--oauth2-secret=your-client-secret
--oauth2-redirect-uri=https://flower.example.com/login

# GitHub OAuth2
--auth=github
--oauth2-key=github-client-id
--oauth2-secret=github-client-secret

# Environment variables
export FLOWER_OAUTH2_KEY=client-id
export FLOWER_OAUTH2_SECRET=client-secret
export FLOWER_OAUTH2_REDIRECT_URI=https://flower.example.com/login

# GitLab OAuth2 with custom domain
--auth=gitlab
export FLOWER_GITLAB_OAUTH_DOMAIN=gitlab.company.com
export FLOWER_GITLAB_AUTH_ALLOWED_GROUPS=dev-team,admin-team
export FLOWER_GITLAB_MIN_ACCESS_LEVEL=30

# GitHub Enterprise
export FLOWER_GITHUB_OAUTH_DOMAIN=github.company.com

# Okta OAuth2
--auth=okta
export FLOWER_OAUTH2_OKTA_BASE_URL=https://company.okta.com/oauth2/default

Usage Examples

Basic Auth Setup

from flower.app import Flower
from tornado.options import options

options.basic_auth = ['admin:secret', 'viewer:readonly']
flower_app = Flower(options=options)

OAuth2 Setup

options.auth = ['google']
options.oauth2_key = 'your-google-client-id'
options.oauth2_secret = 'your-google-client-secret'
options.oauth2_redirect_uri = 'https://flower.company.com/login'

flower_app = Flower(options=options)

Custom Authentication

from flower.views.auth import authenticate

# Custom authentication logic
def custom_auth_check(email):
    # Custom validation logic
    return email in allowed_users or is_admin(email)

# Override authenticate function
original_authenticate = authenticate
def authenticate(pattern, email):
    return custom_auth_check(email) or original_authenticate(pattern, email)

Authentication Flow

Basic Auth Flow

  1. User accesses protected endpoint
  2. Browser prompts for username/password
  3. Credentials validated against configured basic_auth
  4. Access granted/denied based on validation

OAuth2 Flow

  1. User accesses login URL
  2. Redirected to OAuth2 provider
  3. User authenticates with provider
  4. Provider redirects back with authorization code
  5. Flower exchanges code for access token
  6. User email retrieved from provider API
  7. Email validated against auth pattern
  8. Session established if authorized

Security Considerations

  • Use HTTPS in production for all authentication methods
  • Store OAuth2 secrets securely (environment variables)
  • Regularly rotate authentication credentials
  • Use strict email patterns for OAuth2 filtering
  • Monitor authentication logs for suspicious activity
  • Consider session timeout configuration

Install with Tessl CLI

npx tessl i tessl/pypi-flower

docs

application.md

authentication.md

broker.md

command-line.md

events.md

index.md

rest-api.md

tasks.md

utilities.md

web-interface.md

workers.md

tile.json