Reauthentication

Reauthentication asks a signed-in user to verify an authentication factor again before a sensitive action. After the factor succeeds, Forte updates lastReauthenticatedAt on the current session. Your app decides how recent that timestamp must be before it continues.

Client-side API

Reauthentication uses Forte's client-side API. A Forte Service frontend can use the first-party /_forte path. Mobile apps and server-side code must pass the user's session token as a bearer token. Authenticate these calls with the user's session, not FORTE_API_TOKEN.

How reauthentication works

  1. Call getReauthenticationStatus to read lastReauthenticatedAt and availableFactors.
  2. If the user chooses email or SMS, call createReauthenticationChallenge to send a one-time code. Passwords, authenticator codes, and backup codes do not need a challenge.
  3. Call completeReauthentication with the selected factor and credential.
  4. Before the sensitive action runs, call getReauthenticationStatus from your backend. Continue only when lastReauthenticatedAt falls within your freshness window.

Reauthentication does not create or replace a session token. It updates only the current session, and listSessions also returns the timestamp.

Choose an available factor

availableFactors follows this order:

  • If the user has a verified authenticator app or unused backup codes, Forte returns only those factors.
  • Otherwise, Forte returns the user's password when password sign-in is enabled and the user has a password.
  • Forte also returns each verified email or phone that can receive a one-time code through an enabled sign-in channel.

Each email or SMS factor includes a contactMethodId and a masked destination such as a***@example.com. Show each destination as a separate choice. Pass its contactMethodId as targetContactMethodId when you create the challenge.

An impersonation session has no available factors. Passkeys and Google reauthentication are not supported.

Reauthenticate the user

This example uses an email one-time code from a Forte Service frontend. The /_forte path keeps the session cookie first-party.

typescript
import { ForteClient } from "@forteplatforms/sdk";
 
const forte = new ForteClient({ baseUrl: "/_forte" });
const status = await forte.users.getReauthenticationStatus({ projectId });
const emailFactor = status.availableFactors.find(
  (factor) => factor.type === "EMAIL_OTP",
);
 
if (!emailFactor) {
  throw new Error("Email reauthentication is not available");
}
 
await forte.users.createReauthenticationChallenge({
  projectId,
  reauthenticationChallengeRequest: {
    method: "EMAIL_OTP",
    targetContactMethodId: emailFactor.contactMethodId,
  },
});
 
const result = await forte.users.completeReauthentication({
  projectId,
  reauthenticationRequest: {
    method: "EMAIL_OTP",
    credential: codeEnteredByUser,
  },
});
 
console.log(result.reauthenticatedAt);

For a password, authenticator code (TOTP), or backup code (BACKUP_CODE), skip the challenge. Pass the credential directly to completeReauthentication.

Test sandbox challenges

In a sandbox project, a contact method with a fixed test code uses that code for reauthentication. Forte does not send an email or SMS.

Enforce a freshness window

Enforce the window on the backend that performs the sensitive action. Pass the user's session token to Forte, then compare lastReauthenticatedAt with your cutoff. Do not accept a timestamp from the browser.

typescript
const status = await forte.users.getReauthenticationStatus({
  projectId,
  authorization: `Bearer ${sessionToken}`,
});
 
const cutoff = Date.now() - 5 * 60 * 1000;
const isFresh =
  status.lastReauthenticatedAt != null &&
  new Date(status.lastReauthenticatedAt).getTime() >= cutoff;
 
if (!isFresh) {
  return respondNeedsReauthentication();
}
 
performSensitiveAction();

The timestamp applies to the whole session, not to one action. Any action using the same freshness window can accept the same reauthentication.

Handle errors

CodeHTTPCause
REAUTHENTICATION_FACTOR_NOT_AVAILABLE400The factor is not available for this user, project, or session.
REAUTHENTICATION_INVALID_CREDENTIAL400The password, authenticator code, one-time code, or backup code is incorrect.
REAUTHENTICATION_CODE_EXPIRED400The email or SMS code expired or reached the attempt limit.
REAUTHENTICATION_NO_ACTIVE_CHALLENGE400No email or SMS challenge is active. Create a challenge first.
REAUTHENTICATION_RATE_LIMITED429The user requested another code before the resend delay ended.
MFA_REQUIRED401Sign-in MFA is still pending. Complete MFA before reauthentication.

Next steps

Search

Search documentation and console pages