Skip to content

Commit 9afca3e

Browse files
committed
fix(verification): fixed OTP verification
1 parent c345945 commit 9afca3e

File tree

4 files changed

+32
-19
lines changed

4 files changed

+32
-19
lines changed

apps/sim/app/(auth)/signup/signup-form.tsx

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -327,27 +327,24 @@ function SignupFormContent({
327327
return
328328
}
329329

330-
// Handle invitation flow redirect
331-
if (isInviteFlow && redirectUrl) {
332-
router.push(redirectUrl)
333-
return
334-
}
335-
336-
try {
337-
await client.emailOtp.sendVerificationOtp({
338-
email: emailValue,
339-
type: 'email-verification',
340-
})
341-
} catch (err) {
342-
console.error('Failed to send verification OTP:', err)
343-
}
344-
330+
// For new signups, always require verification to prevent bypass
331+
// sendVerificationOnSignUp: true will automatically send the OTP
345332
if (typeof window !== 'undefined') {
346333
sessionStorage.setItem('verificationEmail', emailValue)
347334
localStorage.setItem('has_logged_in_before', 'true')
348-
document.cookie = 'has_logged_in_before=true; path=/; max-age=31536000; SameSite=Lax' // 1 year expiry
335+
336+
// Set cookie flag for middleware check (prevents bypass)
337+
document.cookie = 'requiresEmailVerification=true; path=/; max-age=900; SameSite=Lax' // 15 min expiry
338+
document.cookie = 'has_logged_in_before=true; path=/; max-age=31536000; SameSite=Lax'
339+
340+
// Store invitation flow state if applicable
341+
if (isInviteFlow && redirectUrl) {
342+
sessionStorage.setItem('inviteRedirectUrl', redirectUrl)
343+
sessionStorage.setItem('isInviteFlow', 'true')
344+
}
349345
}
350346

347+
// Always redirect to verification for new signups
351348
router.push('/verify?fromSignup=true')
352349
} catch (error) {
353350
console.error('Signup error:', error)

apps/sim/app/(auth)/verify/use-verification.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,14 @@ export function useVerification({
121121
if (response && !response.error) {
122122
setIsVerified(true)
123123

124-
// Clear email from sessionStorage after successful verification
124+
// Clear verification requirements and session storage
125125
if (typeof window !== 'undefined') {
126126
sessionStorage.removeItem('verificationEmail')
127127

128+
// Clear the verification requirement flag - this prevents the bypass
129+
document.cookie =
130+
'requiresEmailVerification=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
131+
128132
// Also clear invite-related items
129133
if (isInviteFlow) {
130134
sessionStorage.removeItem('inviteRedirectUrl')
@@ -223,6 +227,11 @@ export function useVerification({
223227
// Auto-verify and redirect in development/docker environments
224228
if (isDevOrDocker || !hasResendKey) {
225229
setIsVerified(true)
230+
231+
// Clear verification requirement cookie (same as manual verification)
232+
document.cookie =
233+
'requiresEmailVerification=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
234+
226235
const timeoutId = setTimeout(() => {
227236
router.push('/workspace')
228237
}, 1000)

apps/sim/lib/auth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ export const auth = betterAuth({
156156
},
157157
emailAndPassword: {
158158
enabled: true,
159-
requireEmailVerification: false,
160-
sendVerificationOnSignUp: false,
159+
requireEmailVerification: false, // Keep false - don't break existing users
160+
sendVerificationOnSignUp: true, // Auto-send verification emails
161161
throwOnMissingCredentials: true,
162162
throwOnInvalidCredentials: true,
163163
sendResetPassword: async ({ user, url, token }, request) => {

apps/sim/middleware.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ export async function middleware(request: NextRequest) {
9393
if (!hasActiveSession) {
9494
return NextResponse.redirect(new URL('/login', request.url))
9595
}
96+
97+
// Check if user needs email verification (prevents the bypass vulnerability)
98+
const requiresVerification = request.cookies.get('requiresEmailVerification')
99+
if (requiresVerification?.value === 'true') {
100+
return NextResponse.redirect(new URL('/verify', request.url))
101+
}
102+
96103
return NextResponse.next()
97104
}
98105

0 commit comments

Comments
 (0)