Web-based tool for monitoring and administrating Celery clusters with real-time task tracking and worker management.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Multiple authentication methods including Basic Auth and OAuth2 integration with various providers for securing Flower web interface and API access.
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.
"""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.
"""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.
"""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.
"""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.
"""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
"""# Single user
--basic-auth=admin:password
# Multiple users (comma-separated)
--basic-auth=admin:secret,user:pass
# Environment variable
export FLOWER_BASIC_AUTH=admin:secret# 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# 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/defaultfrom flower.app import Flower
from tornado.options import options
options.basic_auth = ['admin:secret', 'viewer:readonly']
flower_app = Flower(options=options)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)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)Install with Tessl CLI
npx tessl i tessl/pypi-flower