Skip to main content

Authentication

Every CNS request authenticates via a Bearer JWT in the Authorization header — never cookies. That single transport choice is deliberate: Bearer tokens aren't auto-attached cross-origin the way cookies are, so classic CSRF is moot for this API without needing a CSRF token at all (it would only re-enter the picture if CNS were ever forced onto cookie auth).

There are two token shapes, used in different places:

TokenWho holds itUsed on
SSO-JWT (end user)A tenant's own IdP, verified by the identity adapterEvery route: POST /v1/events (as a subject principal), GET /v1/feed, GET /v1/stream, all Admin API routes
Service-JWT (app/publisher)Minted by the app itself from its own ed25519 keyPOST /v1/events only — no other route accepts it

POST /v1/events is the one route that accepts either, and routes between them by a cheap, unverified peek at the token (EdDSA algorithm + a fixed issuer claim, trust.PeekIsServiceToken) purely to decide which verifier to run — that peek grants no trust by itself; the real signature/claims verification always follows. Every other data-plane route, and the entire Admin API, is end-user-only: an app/publisher credential carries no subscribe/read or admin authority, by design (see Authz planes).

The SSO-JWT adapter is IdP-shape-agnostic

The ssojwt identity adapter never hardcodes any one IdP. It's configured with:

  • a signing-key source — either a static HMAC secret, or a JWKS URL (fetched, cached, resolved by kid);
  • issuer and audience to check;
  • configurable claim names for tenant/email/phone, since not every IdP names them the same way;
  • an optional static fallback tenant id, for an IdP whose tokens carry no tenant claim at all.

This is what makes wiring a non-native IdP — e.g. a tenant that authenticates via Supabase Auth instead of a central SSO — a configuration exercise, not a new code path.

Distinguishing "authenticated" from "authorized"

Authentication only answers "who are you." What you're allowed to do — publish, subscribe, or administer — is three separate decisions; see Authz planes.