Files
linumiq_net-web_app/lib/auth/recovery.ts
T

32 lines
1.2 KiB
TypeScript

import { createHash, randomBytes } from 'crypto';
/**
* MFA recovery codes.
*
* GoTrue has no native recovery-code support, so we manage them ourselves in
* the `mfa_recovery_codes` table (service-role only; see migration 0002). We
* only ever persist a SHA-256 hash of each code — the plaintext is shown to the
* user exactly once at generation time. Codes are high-entropy random values,
* so a fast hash is sufficient (no need for bcrypt/per-code salt).
*/
/** Normalise user input so hyphens / case / spacing don't matter on redeem. */
function normalize(code: string): string {
return code.replace(/[^a-z0-9]/gi, '').toLowerCase();
}
/** Stable hash used both when storing and when redeeming a code. */
export function hashRecoveryCode(code: string): string {
return createHash('sha256').update(normalize(code)).digest('hex');
}
/** Generate `n` formatted recovery codes (e.g. `a1b2-c3d4-e5f6`). */
export function generateRecoveryCodes(n = 10): string[] {
const codes: string[] = [];
for (let i = 0; i < n; i++) {
const raw = randomBytes(6).toString('hex'); // 12 hex chars
codes.push(`${raw.slice(0, 4)}-${raw.slice(4, 8)}-${raw.slice(8, 12)}`);
}
return codes;
}