======== Concepts ======== This page explains the core concepts and architecture of the Auth authorization system. Core Concepts ============= Role-Based Access Control (RBAC) --------------------------------- Auth implements a classic RBAC model with three main entities: **Users** Individuals or entities that need access to resources. Users are identified by unique identifiers (typically email addresses or usernames). **Roles** Named collections of permissions. Roles represent job functions or access levels (e.g., "admin", "editor", "viewer"). **Permissions** Atomic capabilities or actions that can be performed (e.g., "edit_content", "delete_user", "view_reports"). The RBAC Model -------------- .. code-block:: text Users (membership)> Roles (permission)> Permissions Example: alice@example.com > admin > manage_users > edit_content > view_content bob@example.com > editor > edit_content > view_content Users are assigned to roles via memberships, and roles are granted permissions. A user inherits all permissions from their assigned roles. Client Keys ----------- Every application or service using Auth must have a unique client key (UUID4). This provides: **Isolation** Different clients have separate authorization scopes. One client's roles and permissions don't affect another's. **Multi-tenancy** Multiple applications can share the same Auth instance without interfering with each other. **Security** Client keys act as API authentication tokens when using the REST interface. Example: .. code-block:: python import uuid # Each app/service gets its own client key webapp_key = str(uuid.uuid4()) api_service_key = str(uuid.uuid4()) workflow_engine_key = str(uuid.uuid4()) # They operate in isolated scopes webapp_auth = Authorization(webapp_key) api_auth = Authorization(api_service_key) Architecture ============ Layered Architecture -------------------- Auth follows a clean, layered architecture: .. code-block:: text   API Layer (Flask)   - REST endpoints   - Request validation   - Response formatting  ,  ¼  Service Layer (Business Logic)   - Authorization rules   - Permission checking   - Audit logging  ,  ¼  Data Access Layer (DAL)   - SQLAlchemy ORM   - Database abstraction   - Encryption/Decryption  ,  ¼  Database (SQLite/PostgreSQL)   - User data   - Role & Permission mappings   - Audit logs   Components ---------- **Authorization Service (``AuthorizationService``)** Core business logic for RBAC operations. Handles permission checks, role assignments, and membership management. **Database Layer (``database.py``)** SQLAlchemy-based ORM models and database connections. Supports both SQLite and PostgreSQL. **REST API (``routes.py``)** Flask routes providing HTTP endpoints for all authorization operations. **Client Libraries** - ``Authorization`` - Direct Python library interface - ``EnhancedAuthClient`` - REST API client for remote access **Security Components** - JWT Authentication - Field-level encryption - Input validation and sanitization - Audit logging Data Model ========== Database Tables --------------- **auth_group** Stores roles with their descriptions. .. code-block:: sql CREATE TABLE auth_group ( id INTEGER PRIMARY KEY, creator TEXT NOT NULL, role TEXT NOT NULL, description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(creator, role) ); **auth_permission** Maps permissions to roles. .. code-block:: sql CREATE TABLE auth_permission ( id INTEGER PRIMARY KEY, creator TEXT NOT NULL, group_id INTEGER NOT NULL, name TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (group_id) REFERENCES auth_group(id) ON DELETE CASCADE, UNIQUE(creator, group_id, name) ); **auth_membership** Maps users to roles. .. code-block:: sql CREATE TABLE auth_membership ( id INTEGER PRIMARY KEY, creator TEXT NOT NULL, group_id INTEGER NOT NULL, user TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (group_id) REFERENCES auth_group(id) ON DELETE CASCADE, UNIQUE(creator, group_id, user) ); **auth_audit_log** Records all authorization changes for compliance and auditing. .. code-block:: sql CREATE TABLE auth_audit_log ( id INTEGER PRIMARY KEY, client_key TEXT NOT NULL, action TEXT NOT NULL, entity_type TEXT NOT NULL, entity_id TEXT, details TEXT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); Permission Checking =================== How Permission Checks Work --------------------------- When you call ``user_has_permission(user, permission)``: 1. Find all roles the user belongs to (via ``auth_membership``) 2. For each role, query all permissions (via ``auth_permission``) 3. Check if the requested permission exists in the result set 4. Return ``True`` if found, ``False`` otherwise Example: .. code-block:: python # Setup auth.add_role('editor') auth.add_permission('editor', 'edit_content') auth.add_membership('bob@example.com', 'editor') # Check can_edit = auth.user_has_permission('bob@example.com', 'edit_content') # Returns: True # Behind the scenes: # 1. Query: bob@example.com ’ ['editor'] # 2. Query: 'editor' ’ ['edit_content', ...] # 3. Check: 'edit_content' in ['edit_content', ...] ’ True Query Methods ------------- Auth provides several ways to query authorization data: **User-centric queries:** - ``get_user_roles(user)`` - Get all roles for a user - ``get_user_permissions(user)`` - Get all permissions for a user - ``user_has_permission(user, permission)`` - Check if user has permission **Role-centric queries:** - ``get_role_members(role)`` - Get all users in a role - ``get_permissions(role)`` - Get all permissions for a role - ``has_permission(role, permission)`` - Check if role has permission **Permission-centric queries:** - ``which_users_can(permission)`` - Find all users with a permission - ``which_roles_can(permission)`` - Find all roles with a permission Audit Trail =========== Every authorization change is logged to the audit table: **Logged Actions:** - Role creation/deletion - Permission grant/revoke - Membership addition/removal **Audit Record Fields:** - ``client_key`` - Which client made the change - ``action`` - Type of operation (create, delete, grant, revoke) - ``entity_type`` - What was modified (role, permission, membership) - ``entity_id`` - Identifier of the entity - ``details`` - Additional context (JSON) - ``timestamp`` - When the change occurred Example audit log query: .. code-block:: python from auth.audit import query_audit_logs # Get all changes by a client logs = query_audit_logs(client_key='abc-123') # Get all permission grants logs = query_audit_logs(action='grant', entity_type='permission') Security Model ============== Defense in Depth ---------------- Auth employs multiple security layers: 1. **Client Authentication** - UUID4 keys for API access 2. **JWT Tokens** - Optional token-based authentication 3. **Input Validation** - Sanitization of all user inputs 4. **SQL Injection Protection** - ORM-based queries 5. **Encryption** - Optional field-level encryption 6. **Audit Logging** - Complete change history Encryption ---------- Auth supports deterministic field-level encryption: **What's Encrypted:** - User identifiers in memberships - Permission names - Optional role descriptions **Why Deterministic:** - Allows querying encrypted data - Same plaintext = same ciphertext - Enables efficient database operations **Trade-offs:** - Pattern analysis possible (acceptable for usernames/permissions) - Full database functionality maintained - No performance impact on queries See :doc:`encryption` for detailed information. Best Practices ============== Role Design ----------- **Keep roles granular:** .. code-block:: python # Good: Specific roles auth.add_role('content_editor') auth.add_role('content_reviewer') auth.add_role('content_publisher') # Avoid: Too broad auth.add_role('content_manager') # Too many permissions **Use hierarchical naming:** .. code-block:: python auth.add_role('admin.system') auth.add_role('admin.department') auth.add_role('user.premium') auth.add_role('user.basic') Permission Design ----------------- **Use verb-noun naming:** .. code-block:: python # Good: Clear action + resource auth.add_permission('role', 'create_user') auth.add_permission('role', 'delete_post') auth.add_permission('role', 'view_analytics') # Avoid: Ambiguous auth.add_permission('role', 'users') auth.add_permission('role', 'manage') **Keep permissions atomic:** .. code-block:: python # Good: Specific permissions 'read_file' 'write_file' 'delete_file' # Avoid: Combined permissions 'file_management' # Too broad Client Key Management --------------------- **Generate unique keys per service:** .. code-block:: python import uuid # Different key for each service web_app_key = str(uuid.uuid4()) mobile_app_key = str(uuid.uuid4()) admin_panel_key = str(uuid.uuid4()) **Store keys securely:** - Use environment variables - Never commit to version control - Rotate keys periodically - Use secrets management systems in production Next Steps ========== - :doc:`python_usage` - Learn the Python API - :doc:`rest_api` - Learn the REST API - :doc:`security` - Security best practices - :doc:`audit_logging` - Working with audit logs