diff --git a/apps/web/app/auth/verify/page.tsx b/apps/web/app/auth/verify/page.tsx index 40424969d..a1977ecf6 100644 --- a/apps/web/app/auth/verify/page.tsx +++ b/apps/web/app/auth/verify/page.tsx @@ -2,6 +2,7 @@ import { redirect } from 'next/navigation'; import { MultiFactorChallengeContainer } from '@kit/auth/mfa'; import { checkRequiresMultiFactorAuthentication } from '@kit/supabase/check-requires-mfa'; +import { requireUser } from '@kit/supabase/require-user'; import { getSupabaseServerComponentClient } from '@kit/supabase/server-component-client'; import pathsConfig from '~/config/paths.config'; @@ -31,9 +32,15 @@ async function VerifyPage(props: Props) { } const redirectPath = props.searchParams.next ?? pathsConfig.app.home; + const auth = await requireUser(client); + + if (auth.error) { + redirect(auth.redirectTo); + } return ( - + diff --git a/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-list.tsx b/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-list.tsx index 875efbb75..6ff42a043 100644 --- a/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-list.tsx +++ b/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-list.tsx @@ -10,7 +10,7 @@ import { ShieldCheck, X } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { toast } from 'sonner'; -import useFetchAuthFactors from '@kit/supabase/hooks/use-fetch-mfa-factors'; +import { useFetchAuthFactors } from '@kit/supabase/hooks/use-fetch-mfa-factors'; import { useSupabase } from '@kit/supabase/hooks/use-supabase'; import { useFactorsMutationKey } from '@kit/supabase/hooks/use-user-factors-mutation-key'; import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert'; @@ -48,8 +48,13 @@ import { MultiFactorAuthSetupDialog } from './multi-factor-auth-setup-dialog'; const MAX_FACTOR_COUNT = 10; -export function MultiFactorAuthFactorsList() { - const { data: factors, isLoading, isError } = useFetchAuthFactors(); +export function MultiFactorAuthFactorsList(props: { userId: string }) { + const { + data: factors, + isLoading, + isError, + } = useFetchAuthFactors(props.userId); + const [unEnrolling, setUnenrolling] = useState(); if (isLoading) { @@ -100,7 +105,7 @@ export function MultiFactorAuthFactorsList() {
- +
); @@ -114,13 +119,14 @@ export function MultiFactorAuthFactorsList() {
- +
{(factorId) => ( setUnenrolling(undefined)} /> @@ -133,11 +139,12 @@ export function MultiFactorAuthFactorsList() { function ConfirmUnenrollFactorModal( props: React.PropsWithChildren<{ factorId: string; + userId: string; setIsModalOpen: (isOpen: boolean) => void; }>, ) { const { t } = useTranslation(); - const unEnroll = useUnenrollFactor(); + const unEnroll = useUnenrollFactor(props.userId); const onUnenrollRequested = useCallback( (factorId: string) => { @@ -261,10 +268,10 @@ function FactorsTable({ ); } -function useUnenrollFactor() { +function useUnenrollFactor(userId: string) { const queryClient = useQueryClient(); const client = useSupabase(); - const mutationKey = useFactorsMutationKey(); + const mutationKey = useFactorsMutationKey(userId); const mutationFn = async (factorId: string) => { const { data, error } = await client.auth.mfa.unenroll({ diff --git a/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-setup-dialog.tsx b/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-setup-dialog.tsx index 3ebb241ee..2644c5d68 100644 --- a/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-setup-dialog.tsx +++ b/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-setup-dialog.tsx @@ -44,7 +44,7 @@ import { Trans } from '@kit/ui/trans'; import { refreshAuthSession } from '../../../server/personal-accounts-server-actions'; -export function MultiFactorAuthSetupDialog() { +export function MultiFactorAuthSetupDialog(props: { userId: string }) { const { t } = useTranslation(); const [isOpen, setIsOpen] = useState(false); @@ -77,6 +77,7 @@ export function MultiFactorAuthSetupDialog() {
setIsOpen(false)} onEnrolled={onEnrollSuccess} /> @@ -90,11 +91,13 @@ export function MultiFactorAuthSetupDialog() { function MultiFactorAuthSetupForm({ onEnrolled, onCancel, + userId, }: React.PropsWithChildren<{ + userId: string; onCancel: () => void; onEnrolled: () => void; }>) { - const verifyCodeMutation = useVerifyCodeMutation(); + const verifyCodeMutation = useVerifyCodeMutation(userId); const verificationCodeForm = useForm({ resolver: zodResolver( @@ -161,6 +164,7 @@ function MultiFactorAuthSetupForm({
verificationCodeForm.setValue('factorId', factorId) @@ -241,11 +245,13 @@ function MultiFactorAuthSetupForm({ function FactorQrCode({ onSetFactorId, onCancel, + userId, }: React.PropsWithChildren<{ + userId: string; onCancel: () => void; onSetFactorId: (factorId: string) => void; }>) { - const enrollFactorMutation = useEnrollFactor(); + const enrollFactorMutation = useEnrollFactor(userId); const [error, setError] = useState(false); const form = useForm({ @@ -385,9 +391,9 @@ function QrImage({ src }: { src: string }) { return {'QR; } -function useEnrollFactor() { +function useEnrollFactor(userId: string) { const client = useSupabase(); - const mutationKey = useFactorsMutationKey(); + const mutationKey = useFactorsMutationKey(userId); const mutationFn = async (factorName: string) => { const { data, error } = await client.auth.mfa.enroll({ @@ -408,8 +414,8 @@ function useEnrollFactor() { }); } -function useVerifyCodeMutation() { - const mutationKey = useFactorsMutationKey(); +function useVerifyCodeMutation(userId: string) { + const mutationKey = useFactorsMutationKey(userId); const client = useSupabase(); const mutationFn = async (params: { factorId: string; code: string }) => { diff --git a/packages/features/auth/src/components/multi-factor-challenge-container.tsx b/packages/features/auth/src/components/multi-factor-challenge-container.tsx index b37fbb379..5e97226bd 100644 --- a/packages/features/auth/src/components/multi-factor-challenge-container.tsx +++ b/packages/features/auth/src/components/multi-factor-challenge-container.tsx @@ -10,7 +10,7 @@ import { useMutation } from '@tanstack/react-query'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; -import useFetchAuthFactors from '@kit/supabase/hooks/use-fetch-mfa-factors'; +import { useFetchAuthFactors } from '@kit/supabase/hooks/use-fetch-mfa-factors'; import { useSignOut } from '@kit/supabase/hooks/use-sign-out'; import { useSupabase } from '@kit/supabase/hooks/use-supabase'; import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert'; @@ -35,7 +35,9 @@ import { Trans } from '@kit/ui/trans'; export function MultiFactorChallengeContainer({ paths, + userId, }: React.PropsWithChildren<{ + userId: string; paths: { redirectPath: string; }; @@ -65,6 +67,7 @@ export function MultiFactorChallengeContainer({ if (!factorId) { return ( { verificationCodeForm.setValue('factorId', factorId); }} @@ -195,12 +198,14 @@ function useVerifyMFAChallenge() { function FactorsListContainer({ onSuccess, onSelect, + userId, }: React.PropsWithChildren<{ + userId: string; onSuccess: () => void; onSelect: (factor: string) => void; }>) { const signOut = useSignOut(); - const { data: factors, isLoading, error } = useFetchAuthFactors(); + const { data: factors, isLoading, error } = useFetchAuthFactors(userId); const isSuccess = factors && !isLoading && !error; diff --git a/packages/supabase/src/hooks/use-fetch-mfa-factors.ts b/packages/supabase/src/hooks/use-fetch-mfa-factors.ts index 7a3e02d55..666aef91d 100644 --- a/packages/supabase/src/hooks/use-fetch-mfa-factors.ts +++ b/packages/supabase/src/hooks/use-fetch-mfa-factors.ts @@ -3,9 +3,9 @@ import { useQuery } from '@tanstack/react-query'; import { useSupabase } from './use-supabase'; import { useFactorsMutationKey } from './use-user-factors-mutation-key'; -function useFetchAuthFactors() { +export function useFetchAuthFactors(userId: string) { const client = useSupabase(); - const queryKey = useFactorsMutationKey(); + const queryKey = useFactorsMutationKey(userId); const queryFn = async () => { const { data, error } = await client.auth.mfa.listFactors(); @@ -22,5 +22,3 @@ function useFetchAuthFactors() { queryFn, }); } - -export default useFetchAuthFactors; diff --git a/packages/supabase/src/hooks/use-user-factors-mutation-key.ts b/packages/supabase/src/hooks/use-user-factors-mutation-key.ts index 9190764cc..b3a3203dd 100644 --- a/packages/supabase/src/hooks/use-user-factors-mutation-key.ts +++ b/packages/supabase/src/hooks/use-user-factors-mutation-key.ts @@ -1,8 +1,3 @@ -import { useUserSession } from './use-user-session'; - -export function useFactorsMutationKey() { - const user = useUserSession(); - const userId = user?.data?.user.id; - +export function useFactorsMutationKey(userId: string) { return ['mfa-factors', userId]; }