Skip to content

refactor: separate authentication and authorization into distinct modules #120

@Besthope-Official

Description

@Besthope-Official

Use Case

The src/auth/ module currently conflates two distinct concerns: authentication (identity verification) and authorization (permission checking). This violates Domain-Driven Design principles and creates ambiguous imports.

Current problems:

  1. Unclear imports: from src.auth import require_permissions - is this authn or authz?
  2. Namespace ambiguity: "auth" traditionally means authentication, but module contains both
  3. Mixed responsibilities: src/auth/__init__.py exports both identity (User, AuthenticationService) and access control (Permission, Role, PermissionService)
  4. DDD violation: Authentication and Authorization are separate bounded contexts

Examples of confusion:

from src.auth import (
    current_user,              # Authentication
    require_permissions,        # Authorization
    AuthenticationService,      # Authentication
    Permission, Role            # Authorization
)

Proposed Solution

Separate into two top-level modules following DDD bounded contexts:

src/
├── auth/                      # Authentication (identity verification)
│   ├── service.py             # AuthenticationService (login/refresh/logout)
│   ├── manager.py             # UserManager (fastapi-users integration)
│   ├── backend.py             # JWT strategy + RefreshTokenManager
│   ├── models.py              # User, OAuthAccount
│   ├── schemas.py             # TokenResponse, UserRead, UserCreate, UserUpdate
│   ├── exceptions.py          # Authentication exceptions
│   └── __init__.py            # Export: current_user, AuthenticationService, User, etc.
│
└── rbac/                      # Authorization (access control)
    ├── service.py             # PermissionService (permission matching logic)
    ├── repository.py          # PermissionRepository (database queries)
    ├── dependencies.py        # require_permissions, require_roles, owner_or_perm
    ├── models.py              # Permission, Role, UserRole, RolePermission
    ├── exceptions.py          # InsufficientPermissionException, InsufficientRoleException
    └── __init__.py            # Export: require_permissions, require_roles, Permission, etc.

Import clarity after refactor:

from src.auth import current_user, AuthenticationService
from src.rbac import require_permissions, require_roles, owner_or_perm

Migration steps:

  1. Create src/rbac/ directory
  2. Move src/auth/rbac.pysrc/rbac/service.py + src/rbac/repository.py + src/rbac/dependencies.py
  3. Extract RBAC models from src/auth/models.pysrc/rbac/models.py
  4. Extract RBAC exceptions from src/auth/exceptions.pysrc/rbac/exceptions.py
  5. Update all imports across codebase
  6. Update tests (tests/auth/test_rbac.pytests/rbac/)
  7. Update documentation and .claude/skills/backend-patterns/SKILL.md

Alternatives Considered

Alternative A: Submodules under src/auth/

src/auth/
├── authn/
└── authz/
  • Pros: Keeps related concepts together
  • Cons: Still ambiguous ("auth" module name unclear), deeper nesting

Alternative B: Rename to be explicit

src/authentication/
src/authorization/
  • Pros: Very clear naming
  • Cons: Verbose, breaks from existing "auth" convention

Why proposed solution is better:

  • "RBAC" already established (branch feat/auth-rbac, file rbac.py)
  • Top-level separation clearer than submodules
  • "auth" for authentication is industry standard
  • "rbac" is self-documenting for authorization

Implementation Notes

Affected files (update imports):

  • src/http/routers/auth.py - uses AuthenticationService
  • src/http/routers/oauth.py - uses current_user
  • src/audit/dependencies.py - may use auth models
  • All test files in tests/integration/test_auth*.py and tests/integration/test_rbac.py
  • .claude/skills/backend-patterns/SKILL.md - documentation references

Dependency considerations:

  • src/rbac/dependencies.py depends on src.auth.current_user (authentication) - this is correct cross-module dependency
  • src/audit/service.py audits both authentication and authorization events - should import from both modules

Breaking changes:

  • All imports from src.auth containing RBAC entities must update
  • External code importing from src.auth import Permission, Role will break

Migration strategy:

  1. Phase 1: Create src/rbac/ with all RBAC code
  2. Phase 2: Add deprecation warnings in src/auth/__init__.py for RBAC exports
  3. Phase 3: Update all internal imports
  4. Phase 4: Remove deprecated exports from src/auth/__init__.py

Testing strategy:

  • All existing tests must pass after refactor
  • Verify no circular import issues
  • Run full integration test suite

Follow DDD bounded contexts:

  • Authentication context: User identity, sessions, tokens
  • Authorization context: Permissions, roles, access control
  • Clear boundaries enable independent evolution

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions