Files
vantage-app/web/lib/stepup.ts
T
mrhid6 3e341b17ec feat(web): step-up modal and MFA settings controls
Adds the global re-authentication modal for guarded routes and the
owner/admin MFA controls on the settings page.

request() in lib/api.ts now intercepts a 403 step_up_required response,
awaits re-authentication through a callback registered by StepUpModal
(lib/stepup.ts), and retries the original request exactly once. The
modal offers TOTP, recovery code and password, since the webauthn
step-up routes (/me/step-up/webauthn/begin and /finish) are not
registered server-side yet; it omits the passkey option rather than
calling a route that does not exist.

me.stepUp posts one factor to /api/me/step-up. The settings page gains
an owner-only "Require MFA" toggle and the members table gains an MFA
column and a "Reset MFA" action, both routed through the existing
PUT /api/settings and DELETE /api/org/users/:id/mfa.
2026-09-16 09:33:50 +00:00

19 lines
700 B
TypeScript

// The step-up broker. `request()` in api.ts lives outside React, so it cannot
// render a dialog itself; instead it calls back into whatever prompt the
// StepUpModal registered when it mounted inside the (app) layout.
type Prompt = (methods: string[]) => Promise<void>;
let prompt: Prompt | null = null;
// The provider registers the real prompt at mount. Before that, or outside the
// app shell, step-up simply fails rather than hanging forever.
export function registerStepUpPrompt(fn: Prompt | null) {
prompt = fn;
}
export async function requestStepUp(methods: string[]): Promise<void> {
if (!prompt) throw new Error("re-authentication is required");
return prompt(methods);
}