Appearance
Two-Factor Authentication (2FA)
The SDK supports TOTP-based two-factor authentication (compatible with Google Authenticator and any standard authenticator app). A player's account is in one of three states, and every state flip fires onAuthStateChanged with the updated User (isTwoFactorEnabled).
Typed structures
typescript
interface TwoFactorSetup {
otpauthUrl: string; // otpauth:// URI; render as a QR code for the authenticator app
secret?: string; // the raw TOTP secret, for manual entry when the player can't scan
}
interface RecoveryCodes {
codes: string[]; // single-use recovery codes; shown ONCE, never retrievable again
}State machine
| State | Entry trigger | Allowed transitions | Side effects |
|---|---|---|---|
DISABLED | Account default | → PENDING_SETUP (enable2FA called) | none |
PENDING_SETUP | enable2FA succeeds | → ENABLED (verify2FA with a correct code) · → DISABLED (setup window expires) | isTwoFactorEnabled still false; no flag change on expiry |
ENABLED | verify2FA succeeds | → DISABLED (disable2FA with a correct code) | isTwoFactorEnabled flips to true; recovery codes issued at this moment |
Setup expiry: an unverified setup expires after 15 minutes with no flag change; the account stays DISABLED. Verifying after expiry fails with AUTH_2FA_INVALID_CODE; the player restarts setup with a fresh enable2FA call.
Method reference
enable2FA(currentPassword)
Starts 2FA setup. Requires the current password (re-auth; see State & Security).
| Param | Type | Required | Description |
|---|---|---|---|
currentPassword | string | yes | The account's current password |
Returns TwoFactorSetup. Errors: AUTH_INVALID_CREDENTIALS (wrong password; see State & Security § Error Taxonomy).
javascript
const setup = await sdk.auth.enable2FA(currentPassword);
showQRCode(setup.otpauthUrl); // render as QR
showManualEntry(setup.secret); // for players who can't scanverify2FA(code)
Confirms setup with a 6-digit code from the app. On success the account is ENABLED and recovery codes are returned; display them once and let the player save them; they are never retrievable again.
| Param | Type | Required | Description |
|---|---|---|---|
code | string | yes | Current 6-digit TOTP code |
Returns RecoveryCodes. Errors: AUTH_2FA_INVALID_CODE (wrong or expired-setup code); common TOO_MANY_ATTEMPTS (attempt cap exceeded; carries retryAfterMs).
javascript
const { codes } = await sdk.auth.verify2FA('123456');
showRecoveryCodesOnce(codes); // 8 single-use codesdisable2FA(code, currentPassword)
Turns 2FA off. Requires a valid current code AND the current password.
| Param | Type | Required | Description |
|---|---|---|---|
code | string | yes | Current 6-digit TOTP code |
currentPassword | string | yes | The account's current password |
Errors: AUTH_2FA_INVALID_CODE, AUTH_INVALID_CREDENTIALS, common TOO_MANY_ATTEMPTS.
javascript
await sdk.auth.disable2FA('123456', currentPassword);Rules
text
GIVEN a logged-in player in DISABLED state
WHEN enable2FA(currentPassword) is called with the correct password
THEN a setup is created (PENDING_SETUP) and TwoFactorSetup is returned;
isTwoFactorEnabled remains false.
GIVEN a PENDING_SETUP within its 15-minute window
WHEN verify2FA(code) is called with a correct 6-digit code
THEN the account becomes ENABLED, isTwoFactorEnabled flips to true,
onAuthStateChanged fires with the updated user, and single-use
recovery codes are returned exactly once.
GIVEN an ENABLED account
WHEN disable2FA(code, currentPassword) is called with a correct code AND password
THEN the account becomes DISABLED, isTwoFactorEnabled flips to false,
and onAuthStateChanged fires with the updated user.
GIVEN an ENABLED account at login
WHEN login succeeds on credentials alone
THEN login throws AUTH_2FA_REQUIRED (TwoFactorRequiredError) carrying a
single-use tempToken valid for 5 minutes; the session is created only
after verifyLogin2FA(tempToken, code) succeeds (see
[Registration & Login](/authentication/login)).Recovery codes: a recovery code entered at the login challenge satisfies the 2FA step exactly like a TOTP code; each code is single-use. Lost-device recovery beyond the codes (locked out with no codes left) is an operator support flow, outside SDK scope.
Operator-configurable values
| Value | Type | Default | Notes |
|---|---|---|---|
| Recovery code count | number | 8 | How many single-use codes are issued |
| Attempt cap / lockout window | number | 5 / 15 min | Per Rate Limiting & Lockout |
| Setup expiry window | number | 15 min | Unverified setups expire, flag unchanged |
TOTP step (30 s) and algorithm are fixed platform-side.
Sandbox
Sandbox divergences: any 6-digit code is accepted; the sandbox does not validate TOTP math; and the seeded account
VIPDana / VipPass123!demonstrates the full 2FA login challenge. See Environments & Sandbox Data.