1- import type { ActionFunctionArgs , LoaderFunctionArgs , MetaFunction } from "@remix-run/node" ;
1+ import type {
2+ ActionFunctionArgs ,
3+ LoaderFunctionArgs ,
4+ MetaFunction ,
5+ Session ,
6+ } from "@remix-run/node" ;
27import { redirect } from "@remix-run/node" ;
38import { Form , useNavigation } from "@remix-run/react" ;
49import React , { useState } from "react" ;
@@ -48,7 +53,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
4853 } ) ;
4954
5055 const session = await getUserSession ( request ) ;
51-
56+
5257 // Check if there's a pending MFA user ID
5358 const pendingUserId = session . get ( "pending-mfa-user-id" ) ;
5459 if ( ! pendingUserId ) {
@@ -59,7 +64,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
5964 // Get flash message for MFA errors
6065 const messageSession = await getMessageSession ( request . headers . get ( "cookie" ) ) ;
6166 const toastMessage = messageSession . get ( "toastMessage" ) ;
62-
67+
6368 let mfaError : string | undefined ;
6469 if ( toastMessage ?. type === "error" ) {
6570 mfaError = toastMessage . message ;
@@ -79,7 +84,7 @@ export async function action({ request }: ActionFunctionArgs) {
7984 try {
8085 const session = await getUserSession ( request ) ;
8186 const pendingUserId = session . get ( "pending-mfa-user-id" ) ;
82-
87+
8388 if ( ! pendingUserId ) {
8489 return redirect ( "/login" ) ;
8590 }
@@ -96,7 +101,7 @@ export async function action({ request }: ActionFunctionArgs) {
96101
97102 if ( action === "verify-recovery" ) {
98103 const recoveryCode = payload . recoveryCode as string ;
99-
104+
100105 if ( ! recoveryCode ) {
101106 return redirectBackWithErrorMessage ( request , "Recovery code is required" ) ;
102107 }
@@ -105,16 +110,15 @@ export async function action({ request }: ActionFunctionArgs) {
105110 await checkMfaRateLimit ( pendingUserId ) ;
106111
107112 const result = await mfaService . verifyRecoveryCodeForLogin ( pendingUserId , recoveryCode ) ;
108-
113+
109114 if ( ! result . success ) {
110115 return redirectBackWithErrorMessage ( request , result . error || "Invalid authentication code" ) ;
111116 }
112117 // Recovery code verified - complete the login
113118 return await completeLogin ( request , session , pendingUserId ) ;
114-
115119 } else if ( action === "verify-mfa" ) {
116120 const mfaCode = payload . mfaCode as string ;
117-
121+
118122 if ( ! mfaCode || mfaCode . length !== 6 ) {
119123 return redirectBackWithErrorMessage ( request , "Valid 6-digit code is required" ) ;
120124 }
@@ -123,7 +127,7 @@ export async function action({ request }: ActionFunctionArgs) {
123127 await checkMfaRateLimit ( pendingUserId ) ;
124128
125129 const result = await mfaService . verifyTotpForLogin ( pendingUserId , mfaCode ) ;
126-
130+
127131 if ( ! result . success ) {
128132 return redirectBackWithErrorMessage ( request , result . error || "Invalid authentication code" ) ;
129133 }
@@ -133,30 +137,29 @@ export async function action({ request }: ActionFunctionArgs) {
133137 }
134138
135139 return redirect ( "/login" ) ;
136-
137140 } catch ( error ) {
138141 if ( error instanceof ServiceValidationError ) {
139142 return redirectWithErrorMessage ( "/login" , request , error . message ) ;
140143 }
141-
144+
142145 if ( error instanceof MfaRateLimitError ) {
143146 return redirectBackWithErrorMessage ( request , error . message ) ;
144147 }
145-
148+
146149 throw error ;
147150 }
148151}
149152
150- async function completeLogin ( request : Request , session : any , userId : string ) {
153+ async function completeLogin ( request : Request , session : Session , userId : string ) {
151154 // Create a new authenticated session
152155 const authSession = await sessionStorage . getSession ( request . headers . get ( "Cookie" ) ) ;
153156 authSession . set ( authenticator . sessionKey , { userId } ) ;
154-
157+
155158 // Get the redirect URL and clean up pending MFA data
156159 const redirectTo = session . get ( "pending-mfa-redirect-to" ) ?? "/" ;
157160 session . unset ( "pending-mfa-user-id" ) ;
158161 session . unset ( "pending-mfa-redirect-to" ) ;
159-
162+
160163 return redirect ( redirectTo , {
161164 headers : {
162165 "Set-Cookie" : await sessionStorage . commitSession ( authSession ) ,
@@ -166,7 +169,7 @@ async function completeLogin(request: Request, session: any, userId: string) {
166169
167170export default function LoginMfaPage ( ) {
168171 const data = useTypedLoaderData < typeof loader > ( ) ;
169- const rawMfaError = ' mfaError' in data ? data . mfaError : undefined ;
172+ const rawMfaError = " mfaError" in data ? data . mfaError : undefined ;
170173 const navigate = useNavigation ( ) ;
171174 const [ showRecoveryCode , setShowRecoveryCode ] = useState ( false ) ;
172175 const [ mfaCode , setMfaCode ] = useState ( "" ) ;
@@ -245,7 +248,7 @@ export default function LoginMfaPage() {
245248 < span className = "text-text-bright" > Verify</ span >
246249 ) }
247250 </ Button >
248- { typeof mfaError === ' string' && < FormError > { mfaError } </ FormError > }
251+ { typeof mfaError === " string" && < FormError > { mfaError } </ FormError > }
249252 </ Fieldset >
250253 < Button
251254 type = "button"
@@ -297,7 +300,7 @@ export default function LoginMfaPage() {
297300 < span className = "text-text-bright" > Verify</ span >
298301 ) }
299302 </ Button >
300- { typeof mfaError === ' string' && < FormError > { mfaError } </ FormError > }
303+ { typeof mfaError === " string" && < FormError > { mfaError } </ FormError > }
301304 </ Fieldset >
302305 < Button
303306 type = "button"
0 commit comments