Concepts

Sessions, JWTs, and JWKS

After authentication, Authio mints two artefacts: a short-lived access token (JWT) and an opaque refresh token. The cookie name is authio_session; its value is the access JWT itself, which lets edge runtimes verify the session locally with no round-trip.

Access token shape

{
  "iss": "https://api.authio.com",
  "aud": "authio",
  "sub": "user_01HX...",
  "act_org": "org_acme",         // optional: present iff user has selected an org
  "act_role": "admin",           // optional: their role in act_org
  "sid": "sess_01HX...",
  "iat": 1742073600,
  "nbf": 1742073600,
  "exp": 1742074500              // 15 minutes by default
}

Tokens are signed with EdDSA (Ed25519) by default; RS256 is available for environments that can’t verify Ed25519. The signing key is per-tenant and rotated every 30 days with an overlap window so existing tokens stay valid until natural expiry.

JWKS endpoint

Public keys are published at /v1/auth/.well-known/jwks.json. The recommended verification path is to fetch this once at boot, cache for ~10 minutes, and verify locally. Both @authio/node and @authio/edge do this for you with sane defaults.

Lifecycle

  • CreatePOST /v1/auth/passkey/login/verify (or any other auth endpoint) sets the cookie + returns the envelope.
  • Select org POST /v1/sessions/select-org. Required exactly once per session for users with multiple memberships. Single-membership users are auto-selected.
  • Switch org POST /v1/sessions/switch-org. Same shape, different audit event (session.org_switched) so security teams can spot pivots.
  • Refresh POST /v1/sessions/refresh. Rotates the refresh token; access token gets a new exp.
  • Revoke POST /v1/sessions/revoke. Affects every org context for this session; revoked sessions are cached in Redis for fast deny at the edge.

Edge verification

The same JWKS endpoint serves any edge runtime. If you’re on Cloudflare Workers, use @authio/cloudflare-workers which can stash the JWKS in a KV namespace. On Vercel Edge / Bun / Deno, @authio/edge works without any platform primitive.