Skip to content

Conversation

HarshMN2345
Copy link
Member

@HarshMN2345 HarshMN2345 commented Sep 12, 2025

What does this PR do?

(Provide a description of what this PR does.)

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

(Write your answer here.)

Summary by CodeRabbit

  • New Features

    • Expanded MFA support: Authenticator app (TOTP), Email, Phone, and Recovery Code with clearer guidance, improved inputs, and easier factor switching.
    • Added callable verifyCurrent action for programmatic verification.
  • Bug Fixes / Improvements

    • Refined verification flow and error handling (inputs no longer auto-clear on errors).
    • Dynamic challenge handling and adjusted on-mount setup to skip or create challenges based on enabled factors.
    • Verify button and prompts now shown only when applicable factors are enabled.
  • Chores

    • Recovery actions (Regenerate/View) disabled when no other MFA methods are enabled to prevent lockout.

Copy link

appwrite bot commented Sep 12, 2025

Console

Project ID: 688b7bf400350cbd60e9

Sites (2)
Site Status Logs Preview QR
 console-qa
688b7cf6003b1842c9dc
Ready Ready View Logs Preview URL QR Code
 console-cloud
688b7c18002b9b871a8f
Ready Ready View Logs Preview URL QR Code

Note

Cursor pagination performs better than offset pagination when loading further pages.

Copy link
Contributor

coderabbitai bot commented Sep 12, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

verify in src/lib/components/mfaChallengeFormList.svelte was expanded to accept a challengeType (default AuthenticationFactor.Totp) and optional factors, and verifyCurrent() was added and exported. verify now validates that a requested factor is enabled when no challenge is provided, and dynamically creates a challenge using the requested factor (not always TOTP). Input handling moved to InputDigits/InputText; errors are tracked and rethrown without auto-clearing inputs. enabledMainFactors and onMount logic were updated to skip MFA if no factors or prefer Totp when available. In src/routes/(console)/account/updateMfa.svelte, Recovery Regenerate/View buttons are disabled when no other methods are enabled.

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title succinctly and accurately summarizes the primary changes: refactoring the MFA challenge form logic and addressing account page issues; it maps to the actual edits in src/lib/components/mfaChallengeFormList.svelte and src/routes/(console)/account/updateMfa.svelte and is concise enough for reviewers scanning history.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-mfa-flow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/routes/(console)/account/updateMfa.svelte (1)

81-90: Fix inverted toast copy when toggling MFA.

The notification uses the current value instead of the target state, so it can announce the opposite action.

Apply:

 async function updateMfa() {
   try {
-      await sdk.forConsole.account.updateMFA({ mfa: !$user.mfa });
+      const nextMfa = !$user.mfa;
+      await sdk.forConsole.account.updateMFA({ mfa: nextMfa });
       await invalidate(Dependencies.ACCOUNT);
       addNotification({
-          message: `Multi-factor authentication has been ${$user.mfa ? 'enabled' : 'disabled'}`,
+          message: `Multi-factor authentication has been ${nextMfa ? 'enabled' : 'disabled'}`,
           type: 'success'
       });
-      trackEvent(Submit.AccountUpdateMfa, { mfa: !$user.mfa });
+      trackEvent(Submit.AccountUpdateMfa, { mfa: nextMfa });
🧹 Nitpick comments (5)
src/routes/(console)/account/updateMfa.svelte (2)

260-264: Show “Recovery” only when a primary method exists.

enabledMethods.length >= 0 is always true. Hiding the section when no main methods are enabled simplifies the UI and avoids dangling actions.

-{#if enabledMethods.length >= 0}
+{#if enabledMethods.length > 0}

175-183: Block deleting the last primary MFA method.

To avoid “recovery-only” accounts (and potential login dead-ends), disable Delete when TOTP is the sole primary method.

If policy allows at least one primary factor at all times, apply:

-<Button
-    text
-    class="is-not-mobile"
-    on:click={() => (showDelete = true)}>Delete</Button>
+<Button
+    text
+    class="is-not-mobile"
+    disabled={enabledMethods.length === 1}
+    on:click={() => (showDelete = true)}>Delete</Button>
src/lib/components/mfaChallengeFormList.svelte (3)

15-19: Align challenge creation in verify() with createChallenge logic.

createChallenge() intentionally skips creating challenges for TOTP and Recovery Code, but verify() will still create one if challenge is falsy. Make creation conditional on factors that require it (Email/Phone) to avoid redundant server calls and inconsistencies.

-            if (!challenge) {
+            if (
+                !challenge &&
+                challengeType !== AuthenticationFactor.Totp &&
+                challengeType !== AuthenticationFactor.Recoverycode
+            ) {
                 challenge = await sdk.forConsole.account.createMFAChallenge({
                     factor: challengeType
                 });
             }

Also applies to: 62-67


26-28: Improve analytics: include factor used.

Capturing which factor was used helps analyze adoption and issues.

-            trackEvent(Submit.AccountLogin, { mfa_used: true });
+            trackEvent(Submit.AccountLogin, { mfa_used: true, factor: challengeType });

50-56: Minor: consistent naming for “primary/main” factors.

Variable is named enabledMainFactors while UI copy refers to “primary methods.” Consider harmonizing naming for maintainability.

Also applies to: 129-134

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7af9402 and f026a6d.

📒 Files selected for processing (2)
  • src/lib/components/mfaChallengeFormList.svelte (3 hunks)
  • src/routes/(console)/account/updateMfa.svelte (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-08T13:20:47.308Z
Learnt from: ItzNotABug
PR: appwrite/console#2316
File: src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte:29-29
Timestamp: 2025-09-08T13:20:47.308Z
Learning: The Form.svelte component in the Appwrite console creates a FormContext with isSubmitting as writable(false) and expects consumers to work with Svelte writable stores, not plain booleans.

Applied to files:

  • src/lib/components/mfaChallengeFormList.svelte
🔇 Additional comments (2)
src/routes/(console)/account/updateMfa.svelte (1)

283-286: Good guard: recovery actions disabled when no methods are enabled.

The new disabled state prevents generating or viewing recovery codes without at least one primary factor. Solid UX safety net.

Also applies to: 289-293

src/lib/components/mfaChallengeFormList.svelte (1)

86-99: Edge case: “recovery-only” accounts bypass the form.

When no primary factors are enabled but recovery codes exist, the template skips MFA entirely (enabledMainFactors.length === 0). Confirm product policy; if recovery-only sign-in should be supported, default to Recovery Code instead of skipping.

Proposed handling:

 onMount(async () => {
-    if (enabledMainFactors.length === 0) {
-        return;
-    }
+    if (enabledMainFactors.length === 0) {
+        if (factors.recoveryCode) {
+            challengeType = AuthenticationFactor.Recoverycode;
+        }
+        return;
+    }
-{#if enabledMainFactors.length === 0}
-    <!-- Skip MFA completely if no factors enabled -->
+{#if enabledMainFactors.length === 0 && !factors.recoveryCode}
+    <!-- Skip MFA completely if no primary factors or recovery code -->
-{#if showVerifyButton && enabledMainFactors.length > 0}
+{#if showVerifyButton && (enabledMainFactors.length > 0 || challengeType === AuthenticationFactor.Recoverycode)}

Also applies to: 101-107, 125-127

@HarshMN2345 HarshMN2345 requested a review from Copilot September 12, 2025 17:39
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the MFA (Multi-Factor Authentication) challenge form logic to provide better UX and fixes issues in the account page. The changes improve factor selection, add smart initialization, and prevent potential user lockout scenarios.

  • Enhanced MFA challenge form with smarter factor initialization and cleaner UI
  • Added validation to prevent users from disabling all MFA methods when recovery codes exist
  • Streamlined factor switching logic with improved messaging and automatic challenge creation

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/routes/(console)/account/updateMfa.svelte Disables recovery code actions when no other MFA methods are enabled to prevent lockout
src/lib/components/mfaChallengeFormList.svelte Major refactor of MFA challenge logic with improved initialization, factor switching, and UI flow

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 1 to 6
<script context="module" lang="ts">
let inputDigitFields: InputDigits;
import { sdk } from '$lib/stores/sdk';
import { invalidate } from '$app/navigation';
import { Dependencies } from '$lib/constants';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { AuthenticationFactor, type Models } from '@appwrite.io/console';
Copy link
Preview

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Module-level imports should be moved to the instance-level script block. The context='module' script should only contain code that needs to be shared across component instances.

Copilot uses AI. Check for mistakes.

Comment on lines 77 to 79
function switchToFactor(factor: AuthenticationFactor) {
createChallenge(factor);
}
Copy link
Preview

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The switchToFactor function is a simple wrapper around createChallenge. Consider removing this wrapper and calling createChallenge directly for better code clarity.

Copilot uses AI. Check for mistakes.

await invalidate(Dependencies.ACCOUNT);
trackEvent(Submit.AccountLogin, { mfa_used: true });
} catch (error) {
inputDigitFields?.clearInputsAndRefocus();
trackError(error, Submit.AccountLogin);
Copy link
Preview

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inputDigitFields?.clearInputsAndRefocus() call was removed from the error handling, but there's no corresponding functionality to clear the input fields on error. This could leave users with invalid codes still displayed.

Suggested change
trackError(error, Submit.AccountLogin);
trackError(error, Submit.AccountLogin);
code = '';

Copilot uses AI. Check for mistakes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/lib/components/mfaChallengeFormList.svelte (1)

2-6: Fix: Move InputDigits import to the instance script.

The InputDigits component is imported in the module script (line 7 is missing), but it's used in the template. Components used in templates must be imported in the instance script to be in scope.

Move the import from the module script to the instance script:

 <script context="module" lang="ts">
     import { sdk } from '$lib/stores/sdk';
     import { invalidate } from '$app/navigation';
     import { Dependencies } from '$lib/constants';
     import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
     import { AuthenticationFactor, type Models } from '@appwrite.io/console';
-    import { InputDigits } from '$lib/elements/forms';
 
 </script>

 <script lang="ts">
     import { onMount } from 'svelte';
-    import { Button, InputText } from '$lib/elements/forms';
+    import { Button, InputText, InputDigits } from '$lib/elements/forms';

Also applies to: 36-36

🧹 Nitpick comments (3)
src/lib/components/mfaChallengeFormList.svelte (3)

50-54: Improve type safety for enabledMainFactors.

The current implementation creates an array with potential false values that are then filtered out. This can be made more type-safe and cleaner.

-// Get enabled non-recovery factors for main factors
-$: enabledMainFactors = [
-    factors.totp && 'totp',
-    factors.email && 'email',
-    factors.phone && 'phone'
-].filter(Boolean);
+// Get enabled non-recovery factors for main factors
+$: enabledMainFactors = (() => {
+    const factors_list: string[] = [];
+    if (factors.totp) factors_list.push('totp');
+    if (factors.email) factors_list.push('email');
+    if (factors.phone) factors_list.push('phone');
+    return factors_list;
+})();

77-79: Consider renaming switchToFactor for clarity.

The function name switchToFactor doesn't clearly indicate that it creates a new challenge. Consider a more descriptive name.

-function switchToFactor(factor: AuthenticationFactor) {
+function switchToFactorAndCreateChallenge(factor: AuthenticationFactor) {
     createChallenge(factor);
 }

Also update all references to this function in lines 143, 154, 165, and 176.


128-182: Simplify the hasSecondaryOptions computation.

The computed variable hasSecondaryOptions has redundant logic that can be simplified for better readability.

-{@const hasSecondaryOptions =
-    enabledMainFactors.length > 1 ||
-    (factors.recoveryCode && challengeType !== AuthenticationFactor.Recoverycode) ||
-    (enabledMainFactors.length === 1 && factors.recoveryCode)}
+{@const hasSecondaryOptions =
+    enabledMainFactors.length > 1 ||
+    (factors.recoveryCode && challengeType !== AuthenticationFactor.Recoverycode)}

The condition (enabledMainFactors.length === 1 && factors.recoveryCode) is already covered by the second condition when there's at least one enabled factor.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f026a6d and afc1512.

📒 Files selected for processing (1)
  • src/lib/components/mfaChallengeFormList.svelte (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-08T13:20:47.308Z
Learnt from: ItzNotABug
PR: appwrite/console#2316
File: src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte:29-29
Timestamp: 2025-09-08T13:20:47.308Z
Learning: The Form.svelte component in the Appwrite console creates a FormContext with isSubmitting as writable(false) and expects consumers to work with Svelte writable stores, not plain booleans.

Applied to files:

  • src/lib/components/mfaChallengeFormList.svelte
🔇 Additional comments (3)
src/lib/components/mfaChallengeFormList.svelte (3)

100-122: LGTM! Well-structured conditional rendering.

The template properly handles all MFA factor types with appropriate user instructions and input components. The use of InputDigits for code-based factors and InputText for recovery codes is correct.


8-31: Verify public API change impact on consumers.
File: src/lib/components/mfaChallengeFormList.svelte (lines 8–31). The verify(...) signature now adds an optional challengeType parameter — confirm no internal or external callers break because of this change. Repo search failed with rg (unrecognized file type: svelte); run locally to find callers:

rg -n -S 'from.*mfaChallengeFormList' || true
rg -n -S 'verify\s*\(' || true
git grep -n 'mfaChallengeFormList' || true

85-97: Don't auto-create email/phone challenges on mount

onMount calls createChallenge(AuthenticationFactor.Email|Phone) which may send email/SMS immediately — confirm createChallenge's implementation and, if it triggers outgoing messages, defer challenge creation to an explicit user action (button/confirm) or add a visible opt‑in/guard.
Location: src/lib/components/mfaChallengeFormList.svelte (lines 85–97).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/lib/components/mfaChallengeFormList.svelte (4)

63-68: Type the reactive list as factors, not strings.

Avoid magic strings; store AuthenticationFactor[] for stronger invariants.

- $: enabledMainFactors = [
-     factors.totp && 'totp',
-     factors.email && 'email',
-     factors.phone && 'phone'
- ].filter(Boolean);
+ $: enabledMainFactors = ([
+     factors.totp && AuthenticationFactor.Totp,
+     factors.email && AuthenticationFactor.Email,
+     factors.phone && AuthenticationFactor.Phone
+ ].filter(Boolean)) as AuthenticationFactor[];

82-86: Harden notification error handling.

error may not always have .message. Fallback to String(error) to avoid blank toasts.

-            addNotification({
-                type: 'error',
-                message: error.message
-            });
+            addNotification({
+                type: 'error',
+                message: (error as { message?: string })?.message ?? String(error)
+            });

128-129: Improve auto-fill UX for OTP inputs.

Enable OS/browser OTP auto-fill.

-    <InputDigits bind:value={code} required autofocus />
+    <InputDigits bind:value={code} required autofocus autocomplete="one-time-code" inputmode="numeric" />

(Apply to TOTP, Email, and Phone sections.)

Also applies to: 133-134, 138-139


35-35: Enrich analytics with factor dimension.

Capture which factor was used.

-            trackEvent(Submit.AccountLogin, { mfa_used: true });
+            trackEvent(Submit.AccountLogin, { mfa_used: true, mfa_factor: challengeType });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between afc1512 and aeb1e1f.

📒 Files selected for processing (1)
  • src/lib/components/mfaChallengeFormList.svelte (6 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-08T13:20:47.308Z
Learnt from: ItzNotABug
PR: appwrite/console#2316
File: src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte:29-29
Timestamp: 2025-09-08T13:20:47.308Z
Learning: The Form.svelte component in the Appwrite console creates a FormContext with isSubmitting as writable(false) and expects consumers to work with Svelte writable stores, not plain booleans.

Applied to files:

  • src/lib/components/mfaChallengeFormList.svelte
🪛 GitHub Actions: Tests
src/lib/components/mfaChallengeFormList.svelte

[error] 1-1: Prettier formatting check failed (command: 'prettier --check .'). Run 'prettier --write' to fix code style issues.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (2)
src/lib/components/mfaChallengeFormList.svelte (2)

1-200: Fix Prettier violations and commit formatted files.

Ran pnpm -s prettier --write . (Prettier v3.6.2). Reformatted: src/lib/components/mfaChallengeFormList.svelte — commit and push these changes to unblock CI.


92-100: Exported instance function is a valid Svelte pattern — no change required.

Svelte allows exporting functions from the instance <script> to expose component methods on the component instance (callable via bind:this). (v4.svelte.dev)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/components/mfaChallengeFormList.svelte (1)

1-41: Fix: module-scoped verify() is inaccessible to the instance script and references undefined identifiers

  • The instance script calls verify(...) (line 93) but exports from <script context="module"> are not visible to the component instance — this will fail at compile time.
  • The module script references sdk, invalidate, Dependencies, Submit, trackEvent, trackError, AuthenticationFactor, and Models without importing them.

Action: move verify() to a shared helper (e.g., src/lib/mfa/verify.ts) and import it into the instance script, or add the missing imports to the module script and do not call the module export from the instance script.

File: src/lib/components/mfaChallengeFormList.svelte — lines 1–41 (also applies to lines 91–99)

♻️ Duplicate comments (1)
src/lib/components/mfaChallengeFormList.svelte (1)

50-50: LGTM: moved InputDigits to instance script

This fixes component scope and compilation.

🧹 Nitpick comments (2)
src/lib/components/mfaChallengeFormList.svelte (2)

58-61: Initialize props to safe defaults and reflect nullable challenge

Make challenge nullable and initialize code to an empty string to avoid undefined access and ensure bindings have a value.

-export let challenge: Models.MfaChallenge;
-export let code: string;
+export let challenge: Models.MfaChallenge | null = null;
+export let code: string = '';

91-99: Good UX: clear code on verification failure

Resetting code on error prevents stale/invalid values from lingering. Consider also re-focusing the input after clearing for faster retry.

 export async function verifyCurrent() {
     try {
         return await verify(challenge, code, challengeType, factors);
     } catch (error) {
         // Clear input fields on verification failure
         code = '';
+        // Optionally re-focus the active input
+        // await tick(); inputRef?.focus();
         throw error;
     }
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aeb1e1f and fee3ac3.

📒 Files selected for processing (1)
  • src/lib/components/mfaChallengeFormList.svelte (6 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-08T13:20:47.308Z
Learnt from: ItzNotABug
PR: appwrite/console#2316
File: src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte:29-29
Timestamp: 2025-09-08T13:20:47.308Z
Learning: The Form.svelte component in the Appwrite console creates a FormContext with isSubmitting as writable(false) and expects consumers to work with Svelte writable stores, not plain booleans.

Applied to files:

  • src/lib/components/mfaChallengeFormList.svelte
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (1)
src/lib/components/mfaChallengeFormList.svelte (1)

63-68: LGTM: enabledMainFactors computation

Compact and reactive; avoids truthiness pitfalls by filtering falsy values.

Comment on lines 70 to 81
async function createChallenge(factor: AuthenticationFactor) {
disabled = true;
challengeType = factor;
code = '';
try {
challenge = await sdk.forConsole.account.createMFAChallenge({ factor });
if (
factor !== AuthenticationFactor.Totp &&
factor !== AuthenticationFactor.Recoverycode
) {
challenge = await sdk.forConsole.account.createMFAChallenge({ factor });
}
} catch (error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Align challenge creation semantics with verify()

createChallenge() avoids creating a challenge for TOTP and RecoveryCode, while verify() (in the original module script) always creates one when challenge is missing. Confirm API expectations and make both paths consistent (either gate by factor or always create). I can update both places once you confirm the API contract.


🌐 Web query:

Does Appwrite’s Account.createMFAChallenge require a challenge for TOTP and RecoveryCode factors, or only for Email/Phone?

💡 Result:

You must create a challenge for all supported factors (email, phone, totp and recoveryCode). Appwrite’s createMFAChallenge accepts totp and recoveryCode as valid factors (not just email/phone) and returns a challenge ID to complete with updateMfaChallenge. [1][2]


Always create an MFA challenge for all factors (include TOTP & RecoveryCode)

Appwrite requires a challenge for all supported factors (email, phone, totp, recoveryCode). In src/lib/components/mfaChallengeFormList.svelte (lines 70–81) remove the guard that skips createMFAChallenge for AuthenticationFactor.Totp and AuthenticationFactor.Recoverycode so createChallenge always calls sdk.forConsole.account.createMFAChallenge({ factor }); align verify() and createChallenge behavior.

🤖 Prompt for AI Agents
In src/lib/components/mfaChallengeFormList.svelte around lines 70 to 81, the
createChallenge function currently skips calling
sdk.forConsole.account.createMFAChallenge for AuthenticationFactor.Totp and
AuthenticationFactor.Recoverycode; remove that conditional guard so
createChallenge always calls sdk.forConsole.account.createMFAChallenge({ factor
}); (preserve existing disabled/challengeType/code handling and try/catch
behavior) to align createChallenge with verify() and ensure an MFA challenge is
created for all factor types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants