Skip to Content
🎉 TestoQA 1.0 is released
Developer GuideArchitectureAuthentication & authorization flow

Authentication Flow

1. Authentication vs Authorization

TestoQA separates:

  • Authentication: Who is the user?
  • Authorization: What is the user allowed to do (within a project/tenant)?

This document covers authentication only: session establishment, identity resolution, and how identity is made available to server-side boundaries.

Authorization logic and enforcement locations are defined in authorization-model.mdx.


2. Entry Points Requiring Authentication

Most tenant-sensitive operations require authentication at the boundary layer:

  • Server Actions that read or mutate tenant data
  • Route Handlers that access tenant data or trigger workflows
  • Any file upload initiation that persists metadata or grants access
  • Any realtime authorization endpoints (if applicable)

Some routes may be public (e.g., marketing pages), but tenant data is never public.


3. Session Establishment (Login)

Authentication is implemented using Auth.js (NextAuth v5) with a session-based model.

At a high level:

  1. A user initiates sign-in.
  2. Auth.js performs provider authentication.
  3. A session is created/persisted (via adapter).
  4. The browser receives a session cookie/token.
  5. Subsequent requests can resolve the session server-side.

Provider and adapter specifics are intentionally not documented here. This file defines the architectural behavior.


4. Session Resolution

Every authenticated request resolves identity server-side. UI state is never trusted as identity.

Where session is resolved

Session resolution occurs within:

  • Server Components (for SSR gating / conditional rendering)
  • Server Actions
  • Route Handlers

What session resolution produces

Session resolution yields a normalized identity, typically including:

  • userId
  • basic user attributes needed for request context resolution

This identity becomes input to RequestContext resolution at boundaries.


5. Identity Propagation Into RequestContext

Authentication alone is not sufficient to perform tenant operations.

Boundaries must create a RequestContext that includes:

  • userId (from session)
  • projectId (resolved and verified; see tenancy-model.mdx)
  • any additional request metadata used for logging/observability

Rule: The RequestContext is resolved at the boundary before doing work.


6. Authenticated Request Flow (Typical)

The typical authenticated request lifecycle:

Browser → Next.js App Router → Server Action / Route Handler → Resolve session (Auth.js) → Construct RequestContext (userId + projectId) → Proceed to authorization (separate step) → Call domain services → Repositories (tenant-scoped) → Prisma → PostgreSQL → Response

Key constraints:

  • Authentication is always resolved server-side.
  • Tenant resolution is explicit; it must not be guessed.
  • Authorization occurs before data access.

7. Unauthenticated Request Handling

When session resolution fails:

  • The request is treated as unauthenticated
  • The system must return an appropriate failure response:
    • redirect to sign-in where applicable (UI routes)
    • 401/unauthorized for API-like handlers (route handlers)

Do not leak information

Unauthenticated responses must not reveal:

  • whether a particular project exists
  • whether a resource exists inside a project
  • membership details

8. Session Expiry and Renewal

Session expiry is expected and must be handled safely:

  • A stale/expired session results in unauthenticated behavior
  • Boundaries must treat session absence as a hard stop for tenant operations
  • UI should handle re-authentication flows gracefully

Renewal mechanisms are implementation details; the architectural invariant is:

No session ⇒ no tenant work.


9. Security Considerations

Client is never authoritative

  • Client state cannot assert identity
  • Client-supplied identifiers must be validated server-side

CSRF posture

Any non-idempotent operation must consider CSRF posture. The architectural requirement is:

  • mutating operations must be protected via framework/auth mechanisms suitable for the session model

Avoid logging sensitive auth artifacts

  • Never log session tokens/cookies
  • Be careful logging headers, especially in error scenarios

10. Review Checklist (Authentication)

  • Does every tenant-sensitive boundary resolve session server-side?
  • Does the boundary fail fast when unauthenticated?
  • Is RequestContext created from trusted sources only?
  • Are unauthenticated responses tenant-safe (no leakage)?
  • Are auth artifacts excluded from logs?
Last updated on