Files
igny8/master-docs/00-system/03-IDENTITY-AND-AUTHENTICATION.md
IGNY8 VPS (Salman) 1dd2d53a8e doce revapm phase 1
2025-12-07 12:03:45 +00:00

5.9 KiB

Identity and Authentication

Purpose

Document how user identity, JWT handling, API keys, and session flows work, including middleware and validation rules.

Code Locations (exact paths)

  • JWT utilities: backend/igny8_core/auth/utils.py
  • Account context middleware: backend/igny8_core/auth/middleware.py
  • DRF authentication classes: backend/igny8_core/api/authentication.py
  • DRF settings for auth/throttle: backend/igny8_core/settings.py
  • User model and roles: backend/igny8_core/auth/models.py
  • Auth URLs and views: backend/igny8_core/auth/urls.py, backend/igny8_core/auth/views.py

High-Level Responsibilities

  • Support multiple auth mechanisms: API key (WordPress bridge), JWT bearer tokens, session auth without CSRF for APIs, and basic auth fallback.
  • Populate tenant/site context alongside user identity so downstream viewsets enforce isolation.
  • Enforce active account/plan presence before serving protected endpoints (except admin/auth routes).

Detailed Behavior

  • Authentication order (DRF DEFAULT_AUTHENTICATION_CLASSES in settings.py): API key → JWT → CSRF-exempt session → basic auth. The first class that authenticates sets request.user; request.account may also be set by API key or JWT.
  • API Key flow (APIKeyAuthentication): expects Authorization: Bearer <api_key> that is not JWT-like; finds an active Site with wp_api_key, loads its account, and selects an active user (owner preferred, else any active developer/owner/admin). Sets request.account and request.site. Rejects short/invalid keys; returns an auth failure if no active user exists.
  • JWT flow (JWTAuthentication): expects Authorization: Bearer <jwt>; decodes via auth.utils.decode_token; only accepts tokens with type == access. Retrieves User by user_id; optional account_id is resolved to Account and set on request.account. Invalid/expired tokens fall through to other auth classes.
  • Session flow (CSRFExemptSessionAuthentication): uses Django session cookies without CSRF enforcement for API calls.
  • Basic auth: last resort; does not set tenant context.
  • Token utilities (auth/utils.py) generate and decode access/refresh tokens using expiries from settings (JWT_ACCESS_TOKEN_EXPIRY, JWT_REFRESH_TOKEN_EXPIRY), embedding user_id, account_id, email, issued/expiry timestamps, and token type.
  • Middleware (AccountContextMiddleware) runs on every request except admin/auth paths: refreshes session users from DB to pick up current account/plan, validates presence of an active plan, sets request.account, and logs out session users when invalid. For JWT-bearing requests it decodes the token directly and sets request.account. If account/plan is missing or inactive, it returns JSON with success=false and appropriate HTTP status.

Data Structures / Models Involved (no code)

  • User with role and account FKs in auth/models.py.
  • Account with plan and billing fields; plan status is used for access gating.
  • Site with wp_api_key for API key auth; SiteUserAccess for per-site grants.
  • PasswordResetToken model for password reset flows.
  • JWT payload fields: user_id, account_id, email, exp, iat, type.

Execution Flow

  • Middleware step: AccountContextMiddleware determines request.account (session or JWT) and validates plan status; skips admin/auth routes.
  • DRF auth step: API key/JWT/session/basic authenticators run in order, potentially setting request.account (API key/JWT) and request.site (API key).
  • Viewsets then apply role/permission checks and tenant/site/sector filtering via base classes in api/base.py.

Cross-Module Interactions

  • All module viewsets rely on request.user and request.account set by the auth stack. Site-aware modules can read request.site when API key auth is used.
  • Role helpers (is_admin_or_developer, is_system_account_user) influence filtering bypass in base viewsets.

State Transitions (if applicable)

  • JWT lifetimes: access tokens default to 15 minutes; refresh tokens to 30 days (configurable in settings).
  • Session users are refreshed on each request to pick up plan/account changes.
  • Password reset tokens track expiry and usage via expires_at and used flags.

Error Handling

  • Middleware returns JSON errors for missing account or inactive plan and logs out session users in those cases.
  • Invalid/expired JWTs cause the JWT authenticator to return None, allowing other auth methods; decoding errors raise InvalidTokenError in utilities.
  • API key auth raises an auth failure when no active user is available for the resolved account.

Tenancy Rules

  • request.account is set early; base viewsets enforce account filtering unless user has admin/developer/system-account privileges.
  • API key auth also sets request.site for integration contexts; site/sector filtering occurs in SiteSectorModelViewSet.

Billing Rules (if applicable)

  • Active plan is required for access (middleware enforces). Credit debits/charges are handled in billing modules, not in the auth layer.

Background Tasks / Schedulers (if applicable)

  • Token generation/validation is synchronous. Background tasks should receive explicit user/account identifiers in their payloads when invoked.

Key Design Considerations

  • Authentication stack is ordered to give integration API keys precedence, then JWT for app clients, then session for browser-based flows.
  • Tenant context must be established before view logic; do not move or remove AccountContextMiddleware.
  • Expiry durations and JWT secrets are centrally configured in settings.py.

How Developers Should Work With This Module

  • Use token helpers from auth/utils.py when issuing tokens; do not handcraft JWTs.
  • Mount new auth-sensitive endpoints under existing routers and rely on DRF auth classes instead of custom header parsing.
  • Ensure new features that require site context can work with API key auth by checking request.site.
  • Keep plan enforcement in place; bypass only for admin/system routes when justified.