chore: redirect after reset password (#37410)
This commit is contained in:
committed by
GitHub
parent
4bfdbe32ac
commit
d2cf1dad46
@@ -60,10 +60,13 @@ const ConfirmResetCodeForm = ({ email }: { email: string }) => {
|
||||
if (user?.factors?.length) {
|
||||
await router.push({
|
||||
pathname: '/forgot-password-mfa',
|
||||
query: { returnTo: '/reset-password' },
|
||||
query: router.query,
|
||||
})
|
||||
} else {
|
||||
await router.push('reset-password')
|
||||
await router.push({
|
||||
pathname: '/reset-password',
|
||||
query: router.query,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useForm } from 'react-hook-form'
|
||||
import { toast } from 'sonner'
|
||||
import { z } from 'zod'
|
||||
|
||||
import { auth } from 'lib/gotrue'
|
||||
import { auth, getReturnToPath } from 'lib/gotrue'
|
||||
import {
|
||||
Button,
|
||||
Form_Shadcn_,
|
||||
@@ -67,7 +67,7 @@ const ResetPasswordForm = () => {
|
||||
|
||||
// logout all other sessions after changing password
|
||||
await auth.signOut({ scope: 'others' })
|
||||
await router.push('/organizations')
|
||||
await router.push(getReturnToPath('/organizations'))
|
||||
} else {
|
||||
toast.error(`Failed to save password: ${error.message}`, { id: toastId })
|
||||
if (!WHITELIST_ERRORS.some((e) => error.message.includes(e))) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { AuthError } from '@supabase/supabase-js'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useRef, useState } from 'react'
|
||||
import { useRef, useState, useEffect } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { object, string } from 'yup'
|
||||
|
||||
@@ -28,10 +28,22 @@ const SignInForm = () => {
|
||||
|
||||
const [captchaToken, setCaptchaToken] = useState<string | null>(null)
|
||||
const captchaRef = useRef<HCaptcha>(null)
|
||||
const [returnTo, setReturnTo] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
// Only call getReturnToPath after component mounts client-side
|
||||
setReturnTo(getReturnToPath())
|
||||
}, [])
|
||||
|
||||
const { mutate: sendEvent } = useSendEventMutation()
|
||||
const { mutate: addLoginEvent } = useAddLoginEvent()
|
||||
|
||||
let forgotPasswordUrl = `/forgot-password`
|
||||
|
||||
if (returnTo && !returnTo.includes('/forgot-password')) {
|
||||
forgotPasswordUrl = `${forgotPasswordUrl}?returnTo=${encodeURIComponent(returnTo)}`
|
||||
}
|
||||
|
||||
const onSignIn = async ({ email, password }: { email: string; password: string }) => {
|
||||
const toastId = toast.loading('Signing in...')
|
||||
|
||||
@@ -68,9 +80,12 @@ const SignInForm = () => {
|
||||
addLoginEvent({})
|
||||
|
||||
await queryClient.resetQueries()
|
||||
const returnTo = getReturnToPath()
|
||||
// since we're already on the /sign-in page, prevent redirect loops
|
||||
router.push(returnTo === '/sign-in' ? '/organizations' : returnTo)
|
||||
let redirectPath = '/organizations'
|
||||
if (returnTo && returnTo !== '/sign-in') {
|
||||
redirectPath = returnTo
|
||||
}
|
||||
router.push(redirectPath)
|
||||
} catch (error: any) {
|
||||
toast.error(`Failed to sign in: ${(error as AuthError).message}`, { id: toastId })
|
||||
Sentry.captureMessage('[CRITICAL] Failed to sign in via EP: ' + error.message)
|
||||
@@ -124,7 +139,7 @@ const SignInForm = () => {
|
||||
|
||||
{/* positioned using absolute instead of labelOptional prop so tabbing between inputs works smoothly */}
|
||||
<Link
|
||||
href="/forgot-password"
|
||||
href={forgotPasswordUrl}
|
||||
className="absolute top-0 right-0 text-sm text-foreground-lighter"
|
||||
>
|
||||
Forgot Password?
|
||||
|
||||
@@ -18,7 +18,11 @@ const signInSchema = object({
|
||||
code: string().required('MFA Code is required'),
|
||||
})
|
||||
|
||||
const SignInMfaForm = () => {
|
||||
interface SignInMfaFormProps {
|
||||
context?: 'forgot-password' | 'sign-in'
|
||||
}
|
||||
|
||||
const SignInMfaForm = ({ context = 'sign-in' }: SignInMfaFormProps) => {
|
||||
const router = useRouter()
|
||||
const signOut = useSignOut()
|
||||
const queryClient = useQueryClient()
|
||||
@@ -38,7 +42,15 @@ const SignInMfaForm = () => {
|
||||
} = useMfaChallengeAndVerifyMutation({
|
||||
onSuccess: async () => {
|
||||
await queryClient.resetQueries()
|
||||
router.push(getReturnToPath())
|
||||
|
||||
if (context === 'forgot-password') {
|
||||
router.push({
|
||||
pathname: '/reset-password',
|
||||
query: router.query,
|
||||
})
|
||||
} else {
|
||||
router.push(getReturnToPath())
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -73,6 +73,11 @@ export const buildPathWithParams = (pathname: string) => {
|
||||
}
|
||||
|
||||
export const getReturnToPath = (fallback = DEFAULT_FALLBACK_PATH) => {
|
||||
// If we're in a server environment, return the fallback
|
||||
if (typeof location === 'undefined') {
|
||||
return fallback
|
||||
}
|
||||
|
||||
const searchParams = new URLSearchParams(location.search)
|
||||
|
||||
let returnTo = searchParams.get('returnTo') ?? fallback
|
||||
|
||||
@@ -86,7 +86,7 @@ const ForgotPasswordMfa: NextPageWithLayout = () => {
|
||||
heading="Complete two-factor authentication"
|
||||
subheading="Enter the authentication code from your two-factor authentication app before changing your password"
|
||||
>
|
||||
<SignInMfaForm />
|
||||
<SignInMfaForm context="forgot-password" />
|
||||
</ForgotPasswordLayout>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user