Skip to main content
Wildo.ai Coming soon

Authentication

Keep sessions usable while credentials rotate

Keep people signed in without treating a long-lived token as permanent authority. Wildo refreshes access through rotating credentials and checks the account’s current state before continuing the session.

A retired token is replaced by the next token, with retries returning to that successor.

Keep sessions usable while credentials rotate

Keep people signed in without treating a long-lived token as permanent authority. Wildo refreshes access through rotating credentials and checks the account’s current state before continuing the session.

A short retry window handles ordinary duplicate refreshes. Reuse outside that window triggers token withdrawal rather than silently extending access.

Example — Retry a refresh without losing the session

A refresh succeeds but its response is lost. Once the successor is cached, a prompt retry with the retired credential can receive that same successor. Replaying it after the grace window is treated differently.

For engineers

Configure session policy at the right level

Wonder Todos’ administrator type declares:

sessionDurationMinutes: 30,
maxConcurrentSessions: 3,

sessionDurationMinutes is the lifetime of the temporary sign-in episode, not the duration of the access JWT it eventually produces. Registration and invitation episodes are created with a 24-hour expiry; idle timeout and subsequent session-store updates also affect how long they remain usable. maxConcurrentSessions controls the number of authenticated sessions. JWT signing material and access/refresh token lifetimes are deployment-authored runtime settings.

The standard client sends the refresh request with the HTTP-only refresh cookie. The endpoint takes an empty body; a JavaScript client should not read, store or submit the refresh token itself. Access-token updates are propagated to API clients and coordinated between same-origin tabs.

The controller reads the cookie after validating the request shape. Selected code from authentication-controller.backend.service.ts:

const ec = await this._getPreAuthExecutionContext();
RefreshTokenBodySchema.parse(req.body || {});
const refreshTokenValue = AuthControllerUtils.extractRefreshTokenFromCookie(req);
if (!refreshTokenValue) {
  throw this.errorBuilder.buildError(ErrorType.VALIDATION, undefined, {
    customMessageReference: ErrorCustomMessageReference.AUTHENTICATION_REFRESH_TOKEN_REQUIRED,
  });
}

Follow the order of the backend checks

CheckWhy it precedes rotation
Token validity and live accountA valid signature does not keep a disabled account active
Authorization versionA session cannot retain an older authority snapshot
Account and session revocationA retry cannot cross a withdrawal
Retired token and grace successorA short duplicate can receive the already-issued successor

AuthTokenIssuerBackendService.refreshAccessToken returns a cached successor when the predecessor is already marked as rotated and its grace entry exists. Concurrent refreshes select one successor in a Redis transaction that also records the retired credential and applies the winner’s session-limit effects. Losing requests receive the stored successor; they do not register extra sessions. If a response is lost after that transaction, a retry can recover the same tokens during the grace window. After the grace window expires, reuse of the retired credential writes the account-wide invalidation fence and reports a distinct reuse event. The raw token is not part of that signal.

Concurrent-session enforcement uses the shared session store and eviction path. A custom authentication integration must preserve these issuance and refresh paths; manually signing a replacement JWT would bypass the session lifecycle that makes the policy meaningful.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.