Skip to content

Authentication and consent

Authentication and consent

Authentication in this backend has two entrypoints and two acceptance gates:

  • api/views/auth_views.py handles classic username/password login and token refresh.
  • api/views/ms_auth_views.py handles Microsoft bearer-token exchange, user creation, tenant binding, and token issuance.
  • api/views/consent_view.py stores and revokes user consent.
  • api/views/license_view.py stores license acceptance.

Login and token refresh

CustomLoginAPIView validates the request body, authenticates the Django user, and returns a custom JWT access/refresh pair. The response also includes user metadata and a has_consented flag derived from UserConsent.

Important invariants:

  • The login endpoint is public but throttled when LOGIN_THROTTLE_ENABLED is set.
  • Invalid credential formats fail before authentication is attempted.
  • Inactive accounts are rejected explicitly.
  • JWT creation failures are surfaced as a server error rather than as a generic auth failure.

TokenRefreshAPIView validates the refresh token and issues a new access token using the custom JWT wrapper.

Microsoft auth

MicrosoftAuthView is the primary federated login path. It:

  1. validates the Microsoft access token via JWKS
  2. resolves or creates a Django User
  3. stores the Microsoft tenant ID on the user’s profile
  4. resolves or creates the internal tenant for that Microsoft directory
  5. creates tenant membership if needed
  6. returns backend tokens plus tenant/profile information

This is the route that couples authentication to tenancy. The response shape includes tenant, tenant_id, ms_profile, and ms_tenant_id so the frontend can initialize the workspace context immediately.

UserConsentAPIView and LicenseAcceptAPIView both gate downstream user flows.

  • Consent can be queried, created, and revoked.
  • System/application accounts bypass consent checks.
  • License acceptance is recorded as a separate user-level flag.

These checks are not cosmetic: document upload and other protected flows depend on them through permission classes such as HasUserConsent.

Cross-cutting dependencies

  • api.authentication.jwt_utils issues and refreshes tokens.
  • api.utils.auth_utils validates Microsoft tokens and resolves Azure tenant IDs.
  • api.models.consent.UserConsent and api.models.license_acceptance.UserLicenseAcceptance persist user acceptance state.
  • api.tenancy.models.TenantMembership is used to bind Microsoft users to internal workspaces.

Lifecycle ordering

sequenceDiagram
participant Client
participant Login as CustomLoginAPIView
participant MS as MicrosoftAuthView
participant JWT as jwt_wrapper
participant Consent as UserConsentAPIView
participant Tenant as TenantMembership
Client->>Login: username/password
Login->>JWT: create_token_pair(user)
Login-->>Client: access/refresh + has_consented
Client->>MS: Microsoft access token
MS->>MS: validate token, resolve user, resolve tenant
MS->>Tenant: get_or_create membership
MS->>JWT: create_token_pair(user, tenant_id)
MS-->>Client: access/refresh + tenant/profile
Client->>Consent: POST /api/v1/consent/
Consent-->>Client: consent persisted

Representative tests

  • tests/unit/auth/test_auth.py — login success and failure branches.
  • tests/unit/auth/test_login_throttle.py — rate limiting for login.
  • tests/unit/auth/test_ms_tenant_org.py — Microsoft tenant/org binding.
  • tests/unit/auth/test_auth_and_tenancy_contracts.py — auth and tenant-contract boundaries.
  • tests/integration/test_authentication.py — end-to-end auth flows.

Scope boundary

This page covers authentication and user-acceptance state only. For tenant resolution and membership enforcement after login, read Tenancy. For upload gates that require consent, read Document processing.