| 1 | export type TwoFactorMethod = "totp" | "otp"; |
| 2 | |
| 3 | const TWO_FACTOR_METHODS: TwoFactorMethod |
| 4 | |
| 5 | /** Auth plugin id used by Better Auth UI's two-factor integration. */ |
| 6 | export const TWO_FACTOR_PLUGIN_ID = |
| 7 | |
| 8 | /** |
| 9 | * `sessionStorage` key holding the methods reported by the sign-in response. |
| 10 | * |
| 11 | * Only the non-sensitive method names are stored, never a code, token, or the two-factor cookie, which stays HTTP-only. |
| 12 | */ |
| 13 | export const TWO_FACTOR_METHODS_STORAGE_KEY = |
| 14 | "better-auth-ui.two-factor-methods"; |
| 15 | |
| 16 | type TwoFactorRedirect |
| 17 | twoFactorRedirect: true |
| 18 | twoFactorMethods?: unknown |
| 19 | }; |
| 20 | |
| 21 | /** Detect the redirect payload Better Auth returns before a second factor. */ |
| 22 | export function isTwoFactorRedirect(data |
| 23 | return ( |
| 24 | typeof data === " |
| 25 | data !== null && |
| 26 | (data as { |
| 27 | ); |
| 28 | } |
| 29 | |
| 30 | /** Narrow arbitrary method names to the challenge views this UI supports. */ |
| 31 | export function parseTwoFactorMethods(methods |
| 32 | if (!Array.isArray |
| 33 | |
| 34 | return TWO_FACTOR_METHODS.filter |
| 35 | } |
| 36 | |
| 37 | /** Persist the enabled method names without blocking sign-in on storage errors. */ |
| 38 | export function storeTwoFactorMethods(methods |
| 39 | if (typeof sessionStorage |
| 40 | |
| 41 | try { |
| 42 | sessionStorage.setItem( |
| 43 | TWO_FACTOR_METHODS_STORAGE_KEY, |
| 44 | JSON.stringify(parseTwoFactorMethods |
| 45 | ); |
| 46 | } catch { |
| 47 | // The challenge falls back to every method when storage is unavailable. |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | /** Read the stored methods, falling back to every supported challenge. */ |
| 52 | export function readTwoFactorMethods(): |
| 53 | if (typeof sessionStorage |
| 54 | |
| 55 | try { |
| 56 | const stored = |
| 57 | if (!stored) |
| 58 | |
| 59 | const methods = |
| 60 | return methods.length |
| 61 | } catch { |
| 62 | return TWO_FACTOR_METHODS; |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | /** Clear stored method hints after the challenge finishes or is abandoned. */ |
| 67 | export function clearTwoFactorMethods() |
| 68 | if (typeof sessionStorage |
| 69 | |
| 70 | try { |
| 71 | sessionStorage.removeItem(TWO_FACTOR_METHODS_STORAGE_KEY |
| 72 | } catch { |
| 73 | // Stale method hints are harmless and must not block navigation. |
| 74 | } |
| 75 | } |