@@ -60,6 +60,7 @@ export function LoginComponent() {
6060 const [ email , setEmail ] = useState ( "" ) ;
6161 const [ mfaStep , setMfaStep ] = useState < "login" | "verify" > ( "login" ) ;
6262 const [ mfaMethod , setMfaMethod ] = useState < string | null > ( null ) ;
63+ const [ availableMfaMethods , setAvailableMfaMethods ] = useState < string [ ] > ( [ ] ) ;
6364 const [ mfaCode , setMfaCode ] = useState ( "" ) ;
6465 const { toast } = useToast ( ) ;
6566 const [ showPassword , setShowPassword ] = useState ( false ) ;
@@ -163,14 +164,17 @@ export function LoginComponent() {
163164 if ( status ?. error ) {
164165 const msg = status . error as string ;
165166
166- // Catch MFA Required signal
167+ // Catch MFA Required signal — format: MFA_REQUIRED:PRIMARY_METHOD:AVAILABLE_METHODS
167168 if ( msg . startsWith ( "MFA_REQUIRED:" ) ) {
168- const method = msg . split ( ":" ) [ 1 ] ;
169- setMfaMethod ( method ) ;
169+ const parts = msg . split ( ":" ) ;
170+ const primaryMethod = parts [ 1 ] ;
171+ const available = parts [ 2 ] ? parts [ 2 ] . split ( "," ) : [ primaryMethod ] ;
172+ setAvailableMfaMethods ( available ) ;
173+ setMfaMethod ( primaryMethod ) ;
170174 setMfaStep ( "verify" ) ;
171175
172- // If it's WebAuthn, we can auto-trigger the biometric prompt
173- if ( method === "WEBAUTHN" ) {
176+ // Only auto-trigger WebAuthn if it's the SOLE method (no TOTP fallback)
177+ if ( primaryMethod === "WEBAUTHN" && available . length === 1 ) {
174178 triggerWebAuthn ( normalizedEmail ) ;
175179 }
176180 return ;
@@ -469,12 +473,36 @@ export function LoginComponent() {
469473 </ Button >
470474 ) }
471475
476+ { /* Method switcher */ }
477+ { availableMfaMethods . length > 1 && (
478+ < Button
479+ variant = "outline"
480+ className = "w-full text-xs gap-2 border-white/10 hover:bg-white/5"
481+ onClick = { ( ) => {
482+ const altMethod = mfaMethod === "TOTP" ? "WEBAUTHN" : "TOTP" ;
483+ setMfaMethod ( altMethod ) ;
484+ setMfaCode ( "" ) ;
485+ if ( altMethod === "WEBAUTHN" ) {
486+ triggerWebAuthn ( email ) ;
487+ }
488+ } }
489+ disabled = { isLoading }
490+ >
491+ { mfaMethod === "TOTP" ? (
492+ < > < Fingerprint className = "h-4 w-4" /> Use Passkey Instead</ >
493+ ) : (
494+ < > < Smartphone className = "h-4 w-4" /> Use Authenticator Instead</ >
495+ ) }
496+ </ Button >
497+ ) }
498+
472499 < Button
473500 variant = "ghost"
474501 className = "w-full text-xs text-gray-500 hover:text-white"
475502 onClick = { ( ) => {
476503 setMfaStep ( "login" ) ;
477504 setMfaCode ( "" ) ;
505+ setAvailableMfaMethods ( [ ] ) ;
478506 } }
479507 >
480508 Back to credentials
0 commit comments