Faroe

Account recovery

This page uses the JavaScript SDK.

Faroe supports recovery codes, which can be used to reset a user's second factors.

Use Faroe.getUserRecoveryCode() to get the user's recovery code. The code should displayed when the user first registers a second factor and should be accessible anytime after verifying their second factor.

const recoveryCode = await faroe.getUserRecoveryCode(faroeUserId);

Use Faroe.resetUser2FA() to reset the user's second factors with a recovery code. This will delete the user's TOTP credential and generate a new recovery code. Set the totp_registered user attribute to false.

import { FaroeError } from "@faroe/sdk";

import type { FaroeUser } from "@faroe/sdk";

async function handleReset2FARequest(
    request: HTTPRequest,
    response: HTTPResponse
): Promise<void> {
    const clientIP = request.headers.get("X-Forwarded-For");

    const { session, user } = await validateRequest(request);
    if (session === null) {
        response.writeHeader(401);
        response.write("Not authenticated.");
        return;
    }
    if (!user.totpRegistered) {
        response.writeHeader(403);
        response.write("Not allowed.");
        return;
    }

    let code: string;

    // ...

    try {
        await faroe.resetUser2FA(user.id, recoveryCode);
    } catch (e) {
        if (e instanceof FaroeError && e.code === "INCORRECT_CODE") {
            response.writeHeader(400);
            response.write("Incorrect code.");
            return;
        }
        if (e instanceof FaroeError && e.code === "TOO_MANY_REQUESTS") {
            response.writeHeader(429);
            response.write("Please try again later.");
            return;
        }
        response.writeHeader(500);
        response.write("An unknown error occurred. Please try again later.");
        return;
    }

    await setUserAsNot2FARegistered(user.id);
    await setSessionAsNot2FAVerified(session.id);

    // ...
}

Use Faroe.regenerateUserRecoveryCode() to generate a new recovery code. Make sure that the user is 2FA-verified.

async function handleReset2FARequest(
    request: HTTPRequest,
    response: HTTPResponse
): Promise<void> {
    const clientIP = request.headers.get("X-Forwarded-For");

    const { session, user } = await validateRequest(request);
    if (session === null) {
        response.writeHeader(401);
        response.write("Not authenticated.");
        return;
    }
    if (!session.twoFactorVerified) {
        response.writeHeader(403);
        response.write("Not allowed.");
        return;
    }

    let recoveryCode: string;
    try {
        recoveryCode = await faroe.regenerateUserRecoveryCode(user.id);
    } catch (e) {
        response.writeHeader(500);
        response.write("An unknown error occurred. Please try again later.");
        return;
    }

    // ...
}