Qeet Docs

Sessions

ES256 access tokens, refresh-token rotation with theft detection, per-account lockout, and session list/revoke.

Authentication issues a token pair: a short-lived ES256 access JWT and a rotating refresh token, both tied to a server-side session you can list and revoke. This page covers the token model, rotation + theft detection, lockout, and session management.

The token pair

TokenPair
JSON
{
  "access_token": "eyJhbGciOiJFUzI1Ni…",
  "token_type": "Bearer",
  "expires_at": "2026-06-04T12:15:00Z",
  "refresh_token": "…",
  "session_id": "…",
  "user_id": "…",
  "tenant_id": "…"
}
  • Access token — an ES256 JWT. Verify it offline against the public JWKS (/.well-known/jwks.json): signature, expiry, issuer, audience. No per-request network call.
  • Refresh token — opaque; exchange it for a fresh pair at /v1/auth/refresh.
TypeScript
const claims = await qeetid.sessions.verify(accessToken);
// claims.userId, claims.tenantId, claims.sessionId

Why ES256 + JWKS

Tokens are signed with ECDSA P-256 (asymmetric). The JWKS is public, so any service verifies tokens without a shared secret. Signing keys carry an RFC 7638 kid, retire on a grace window, and are guarded against alg-confusion. The SDKs cache the JWKS and refetch on an unknown kid.

Refresh-token rotation + theft detection

Each refresh rotates the token: the old refresh token is invalidated and a new one issued. If a previously-rotated (i.e. stolen and replayed) refresh token is ever presented, Qeet ID revokes the entire token chain for that session and audits the event — so a leaked token can't be used silently.

POST/v1/auth/refreshRotate the token pair
Bash
curl -X POST https://api.qeetid.com/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token":"…"}'

Next.js does this for you

@qeetid/nextjs middleware refreshes a near-expiry session silently — it calls the token endpoint, persists the rotated refresh token in the encrypted cookie, and re-runs the request — so users aren't bounced to login.

Account lockout

On top of distributed IP rate limiting, Qeet ID applies a per-account failed-attempt throttle and temporary lockout to blunt credential stuffing. Locked accounts return 429 on login until the window clears. This is on by default.

List & revoke sessions

For an account-security screen, list the user's active sessions and let them revoke any one. logout revokes the caller's current session.

GET/v1/auth/sessionsList the caller's sessions
DELETE/v1/auth/sessions/{id}Revoke a session
POST/v1/auth/logoutRevoke the current session
TypeScript
const sessions = await qeetid.sessions.list();
await qeetid.sessions.revoke(sessionId);

Password reset revokes all of a user's sessions (see Sign-up & passwords).

Who am I

/v1/auth/me returns the caller's current principal context (user, tenant, session) — handy for hydrating an app shell.

GET/v1/auth/meCurrent principal context

Always verify, never trust

Authorization decisions must be based on a verified access token (or a server-side session lookup), never on cookie presence alone. Verify the JWT signature and expiry on every protected request.

On this page