Kyndex
API Conventions

Session Lifecycle

Session states, the browser bind protocol, how to unlock a locked session, and how to end one.

Endpoint schemas and parameter details live in the API Reference. This page covers session behavior — what states a session can be in, how browser clients finalize sessions, how to unlock a locked session, and how to end one.

Session States

Every access token maps to a KV entry that records the session's current state. A session is either locked or unlocked, depending on whether owner_token and user_member_token are stored in that entry.

Think of a locked session as a library card that proves you're a member but doesn't tell the librarian which books are yours. The access token gets you through the door. The owner_token and user_member_token — derived from your personal key material on your device — tell the server which records belong to you. Without them, the server has no way to locate your documents or entity memberships.

StateWhat it carriesWhat it can do
UnlockedAccess token + owner_token + user_member_tokenFull API access — documents, entities, search, deliveries
LockedAccess token onlyAuth operations and token refresh only

Locked sessions arise in two situations:

  • Account recoveryPOST /auth/recovery returns a locked session intentionally. Your device decrypts the recovered key material and calls PATCH /auth/recovery to receive an unlocked token.
  • Browser loginPOST /auth/opaque/authenticate-finish issues a 60-second pending access token. Your device must complete the bind protocol before the session can act on data.

The Browser Bind Protocol

Your device cannot safely receive a refresh token in a login response — it would be exposed to the JavaScript environment before being stored securely. Instead, your device derives the refresh token locally using OPRF evaluation, then binds the session server-side.

Step 1 — Receive the Pending Access Token

POST /auth/opaque/authenticate-finish returns a short-lived pending access token with a 60-second TTL. This token is accepted on only two endpoints — POST /auth/session/refresh-eval and POST /auth/session/bind — until it expires or is replaced by a full token at bind.

Step 2 — Evaluate the OPRF

POST /auth/session/refresh-eval accepts a blinded ristretto255 point. The server multiplies it by its OPRF key scalar and returns the evaluated result. The server never learns your device's refresh secret; your device never learns the OPRF key.

Your device unblinds the result to derive the refresh token locally.

Step 3 — Bind the Session

POST /auth/session/bind finalizes the session using the OPRF-derived refresh_token:

  1. Validates the pending KV entry (pending: true must be set)
  2. Creates a DB session row keyed by SHA-256 of the refresh token
  3. Issues a new, non-pending access token (15-minute TTL)
  4. Deletes the pending KV entry
  5. Sets the kyndex_rt HttpOnly cookie containing the refresh token

After this step the session is full and unlocked. The server has no record of what refresh token your device holds — only its hash.

Unlocking a Locked Session

Pass owner_token and user_member_token in the refresh body alongside the refresh token:

POST /auth/tokens/refresh
Content-Type: application/json

{
  "refresh_token": "<base64-encoded 32 bytes>",
  "owner_token": "<base64-encoded 32 bytes>",
  "user_member_token": "<base64-encoded 32 bytes>"
}

The server stores these values in the new access token's KV entry. All requests using the new token are treated as unlocked.

This is the standard path after account recovery: POST /auth/recovery returns a locked session, your device decrypts its recovered key material and derives the two tokens, then calls POST /auth/tokens/refresh to receive an unlocked access token.

Endpoints That Require an Unlocked Session

Requests to these endpoints with a locked session return 401 with error code SESSION_LOCKED. The message is: session is locked; provide owner_token and user_member_token via token refresh.

DomainAffected endpoints
DocumentsCreate, list, reservations, OCR result, consumer indexes
EntitiesList, add member, manage members
DeliveriesDiscover, received, reserve, create, lifecycle
SearchDocument search
JobsGet job status

All auth, token refresh, and public endpoints accept locked sessions.

Ending a Session

Both logout routes require a valid access token and return 204 No Content on success. The kyndex_rt cookie is cleared automatically for browser clients.

EndpointScopeBody
DELETE /auth/sessions/currentCurrent session onlyNone
DELETE /auth/sessionsAll sessions{ "revocation_token": "<base64 32 bytes>" }

The revocation_token is issued during login alongside the access and refresh tokens. It authorizes bulk invalidation of every session tied to the account. Store it alongside your refresh token — if it is lost, all-session logout is unavailable until the next login.

On this page