Disciplines · Decisions (ADRs)

ADR-0072: OSHUN Customer Auth and Session Model

OSHUN V1 already decided that customer identity and sessions must be shared across domains, but the current implementation is still fragmented at the exact surface boundaries this task is meant to settle.

Accepted · 2026-03-27
8sections6 minread

On this page

Status: Accepted Date: 2026-03-27 Authors: OSHUN Platform Engineering, OSHUN Web Engineering, OSHUN Mobile Engineering Reviewers: Security, Product, Tara, Veritas, Nyx, Arete, Nisaba leads Supersedes: docs/adr/ADR-0016-shared-identity-and-cross-domain-session-model.md Superseded by: N/A

Context and Problem Statement#

OSHUN V1 already decided that customer identity and sessions must be shared across domains, but the current implementation is still fragmented at the exact surface boundaries this task is meant to settle.

Today, the repo has all of these contradictions at once:

  • web middleware protects customer routes with oshun-session / __session cookies
  • the web AuthProvider still hydrates access and refresh tokens from localStorage
  • the installable PWA is the same apps/oshun/web runtime, but the auth model is not written down as "same as web"
  • mobile has no canonical customer auth runtime yet and still uses memory-backed profile/session-adjacent state
  • the BFF currently authorizes only bearer-style dev tokens rather than the mixed cookie-plus-bearer boundary the product actually needs
  • the shared auth package does not publish the full customer-session contract, and older docs still omit nisaba

That ambiguity blocks the next tasks in the backlog:

  • sign-up / sign-in / sign-out flows
  • refresh, expiration, and re-auth behavior
  • device/session management
  • onboarding continuity and cross-device preference sync

Without one canonical model, each of those tasks would keep re-deciding transport, storage, expiry, and re-entry rules.

Decision Drivers#

  • One-account continuity: a customer signs in once and keeps continuity across Tara, Veritas, Nyx, Arete, and Nisaba.
  • Surface fit: web/PWA and mobile need one shared model, but not identical transport mechanics.
  • Security posture: refresh tokens need rotation, revocation, and device scoping.
  • Implementation leverage: the shared auth package must publish the model in code so web, mobile, and BFF work can converge on it.
  • Operational clarity: session expiry, revocation, and step-up events need one shared taxonomy.

Considered Options#

Option 1: Keep separate auth/session models per surface#

Description: let web, PWA, and mobile each keep their own transport and storage model, then align only loosely at the API layer.

Pros:

  • Lowest short-term migration cost.

Cons:

  • Preserves the current contradictions.
  • Makes cross-device/session management much harder.
  • Keeps sign-in, logout, and expiry behavior inconsistent.

Description: make mobile mirror web/PWA by depending on cookie-backed session state everywhere.

Pros:

  • Simplifies one branch of BFF handling.

Cons:

  • Poor fit for native mobile networking and secure storage.
  • Makes offline/bootstrap behavior awkward on mobile.
  • Treats install/runtime differences as if they do not matter.

Option 3: One shared customer session authority with surface-specific transport rules (Chosen)#

Description: define one customer identity and session authority for all domains and surfaces, but explicitly split the transport/storage boundary by surface: cookie-backed same-origin BFF sessions for web/PWA, secure bearer-token flows for mobile.

Pros:

  • Matches real runtime constraints without fragmenting the identity model.
  • Gives follow-on tasks one normative contract.
  • Keeps security rules strong and explicit.

Cons:

  • Requires web, mobile, and BFF implementation cleanup in follow-on tasks.
  • Requires older auth docs and helper code to be brought into conformance.

Decision Outcome#

Chosen option: Option 3.

Normative Identity Rule#

OSHUN customers have one canonical identity and one customer-session authority across:

  • web
  • pwa
  • mobile

That identity applies across all customer domains:

  • tara
  • veritas
  • nyx
  • arete
  • nisaba

Domain surfaces do not own independent customer identities or refresh-token families.

Normative Session Artifacts#

Every authenticated customer session is defined by the same core artifacts:

  • oshun_user_id / token sub
  • session_id / token sid
  • short-lived access token
  • rotating refresh token family
  • server-owned per-device session registry record

The canonical access-token target lifetime is 10-15 minutes.

Refresh tokens are long-lived, device-scoped, rotating, and server-revocable.

Surface Transport Rule#

The transport boundary is canonical by surface:

  • web: same-origin cookie-backed customer session to the OSHUN web/BFF runtime
  • pwa: same as web, because the installable PWA is the same browser-origin runtime
  • mobile: bearer access token to the BFF/API layer

The BFF is the stable trust boundary between shells and downstream domain/data services.

Storage Rule#

  • web and pwa
    • refresh/session cookie lives in HttpOnly, Secure, same-origin cookies
    • access token is ephemeral runtime state only
    • long-lived customer auth tokens must not be persisted in localStorage
  • mobile
    • refresh token and customer session metadata live only in secure encrypted device storage
    • access token may be cached only in secure storage and memory, never in plain AsyncStorage

Session State Taxonomy#

Customer session state is canonicalized as:

  • active
  • refresh-required
  • reauth-required
  • revoked
  • expired

This taxonomy is the shared contract for web, mobile, BFF, telemetry, and device-management surfaces.

Assurance Rule#

The canonical customer assurance levels are:

  • anonymous
  • standard
  • step-up

step-up means the customer must satisfy additional verification before a sensitive action proceeds, but it does not create a second identity model.

Re-Authentication Rule#

Re-authentication is required only for explicit policy events, not because the customer switched domains. The canonical re-auth triggers are:

  • refresh token expired
  • session revoked or refresh reuse detected
  • step-up required for a sensitive action
  • suspicious account or device activity
  • sensitive account-change confirmation

BFF Boundary Rule#

The BFF must converge on this contract:

  • web/PWA requests are authenticated through same-origin cookie session validation and any required access-token exchange/introspection happens behind that boundary
  • mobile requests are authenticated through bearer access tokens
  • downstream domain adapters do not own refresh tokens and do not become the customer session authority

Customer Entry and Continuity Rule#

The customer auth/session model is continuous across:

  • public marketing/app entry
  • /welcome
  • /onboarding
  • authenticated shell routes
  • domain entry and cross-domain switching

Onboarding is customer-profile capture inside the same session model, not a parallel authentication model.

Device and Session Management Rule#

The canonical session registry is per device/session. Customers must be able to:

  • list active sessions/devices
  • identify the current session
  • revoke a single session
  • revoke all sessions
  • see enough metadata to understand device and surface context

That metadata includes, at minimum, session id, timestamps, device identity, and surface/runtime context.

Shared Package Rule#

libs/oshun/auth is the canonical shell-facing customer auth contract package.

It must publish:

  • shared customer auth/session types
  • surface-specific policy publication
  • shared session state and assurance taxonomy
  • session/device metadata contract
  • secure storage helpers that preserve canonical session metadata

Explicit Non-Conformance Note#

As of this ADR's publication, the current implementation is knowingly out of conformance in several places:

  • web client auth still uses localStorage
  • mobile customer auth runtime is not fully implemented
  • BFF auth middleware is still dev-token oriented

Those mismatches are intentional follow-on scope for:

  • V1-CSH-042
  • V1-CSH-043
  • V1-CSH-044

This ADR settles the contract those tasks must implement.

Architecture Implications#

  • the web customer shell must converge from localStorage token hydration to the cookie-plus-memory model
  • the installable PWA must inherit the exact same auth/session contract as web
  • mobile must add a real secure-session runtime rather than memory-only customer auth behavior
  • BFF middleware must support cookie-backed web/PWA auth and bearer mobile auth under one shared customer-session authority
  • device/session management surfaces must be backed by the canonical session id and per-device registry model

Acceptance Criteria#

V1-CSH-041 is complete only when all criteria below are true:

  1. A canonical ADR supersedes the older cross-domain session ADR.
  2. The shared auth package publishes the customer auth/session model in code.
  3. Shared auth types include the session-state, assurance, surface, transport, storage, and device/session metadata contract.
  4. Secure auth session persistence no longer drops canonical session metadata.
  5. Documentation explicitly records current non-conforming implementations for follow-on tasks.
  • docs/adr/ADR-0014-oshun-web-and-pwa-strategy.md
  • docs/adr/ADR-0016-shared-identity-and-cross-domain-session-model.md
  • docs/adr/ADR-0062-oshun-mobile-shell-relationship-model.md
  • docs/adr/ADR-0063-oshun-customer-admin-shell-relationship-model.md

References#

  • apps/oshun/web/src/middleware.ts
  • apps/oshun/web/src/lib/auth-context.tsx
  • apps/oshun/mobile/src/network/oshun-bff-client.ts
  • apps/oshun/mobile/src/profile/store.ts
  • apps/oshun/bff/src/middleware/authz.ts
  • libs/oshun/auth/src/types.ts
  • libs/oshun/auth/src/customer-auth-model.ts
  • libs/oshun/auth/src/session-store.ts