Skip to main content
Wildo.ai Coming soon

Authentication

End access across a person’s sessions

Withdraw a person’s existing tokens across devices when they sign out everywhere or a credential needs to be replaced. Wildo checks the revocation state during token use and refresh, rather than waiting only for normal expiry.

Signing out everywhere from one account revokes its laptop, phone and tablet sessions.

End access across a person’s sessions

Withdraw a person’s existing tokens across devices when they sign out everywhere or a credential needs to be replaced. Wildo checks the revocation state during token use and refresh, rather than waiting only for normal expiry.

Individual-session logout remains a separate action, so ending one session does not have to end all the others.

Example — Respond to a compromised password

A password reset withdraws the person’s previous tokens. Another device cannot keep refreshing the old session after the reset.

For engineers

Use the account-wide revocation path

The authentication controller exposes logoutAll for the current user. Credential-reset services also use the issuer’s account-wide invalidation method. This is its current implementation:

public async invalidateAllTokensForUser(userId: string): Promise<void> {
  const nowSeconds = Math.floor(Date.now() / 1000);
  const refreshTokenDays = this.appConfigService.config.jwt.refreshTokenExpirationDays;
  await this.redisService.set(
    `${AUTH_REDIS_KEYS.TOKEN_INVALID_BEFORE}${userId}`,
    nowSeconds,
    { ttl: refreshTokenDays * 86400 },
  );
  this.logDebug('All tokens invalidated for user', { userId, invalidBefore: nowSeconds });
}

The fence expresses which earlier tokens are no longer admissible. The JWT guard, execution-context creation and refresh path consult it. A custom credential-changing flow must use the owning service rather than update the password hash and leave existing sessions untouched.

Choose the scope of logout deliberately

invalidateSession(sessionId) is the sibling for one login session. Account-wide invalidation affects the user’s earlier sessions; per-session invalidation withdraws only the selected one. Cross-tab logout separately clears the current browser’s visible state and client credentials.

Treat the revocation second as part of the boundary

The shared evaluateUserTokenInvalidationFence compares whole-second issuance times with the stored revocation second. It deliberately uses an inclusive comparison:

return { isRevoked: issuedAtSeconds <= invalidBefore, invalidBefore };

A token issued before the boundary is refused, and so is one issued in the same second. A login racing the revocation can therefore obtain a token that is immediately rejected: those timestamps cannot distinguish issuance just before the revocation from issuance just after it. Sign in again after that second has passed; do not relax the comparison or keep retrying the withdrawn token.

Token issuance timeThis timestamp fence’s verdict
Before the revocation secondRevoked
In the revocation secondRevoked, including a concurrent fresh login
After the revocation secondNot revoked by this fence; all other checks still apply

The atomic refresh publication path repeats the inclusive comparison inside Redis, so a revocation arriving while a successor is being signed is checked again before publication. Timestamp revocation, authorization-version changes and individual-session withdrawal are distinct checks; passing one does not bypass another. Test the equality case alongside an older token and a genuinely later issuance.

Understand the observed result

The next guarded request or refresh with a withdrawn token is refused. This does not reverse requests that already completed. Refresh checks revocation before returning a cached successor, so its short retry window cannot preserve access past a revocation. Keep the distinction between local interface cleanup, one-session logout and account-wide token withdrawal explicit in custom security controls.

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.