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
{
"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.
const claims = await qeetid.sessions.verify(accessToken);
// claims.userId, claims.tenantId, claims.sessionIdWhy 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.
/v1/auth/refreshRotate the token paircurl -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.
/v1/auth/sessionsList the caller's sessions/v1/auth/sessions/{id}Revoke a session/v1/auth/logoutRevoke the current sessionconst 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.
/v1/auth/meCurrent principal contextAlways 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.
MFA & step-up
TOTP + recovery codes, email/SMS OTP factors, WebAuthn as a second factor, and step-up MFA gated by a recent-verification window.
OIDC / OAuth provider
Qeet ID is a full OpenID Connect provider — discovery, JWKS, dynamic client registration, Authorization Code + PKCE, hosted login & consent, ES256 ID tokens, device grant, and M2M.