Implement redirect control in multi-factor auth container

The update adds a rerouting functionality upon successful multi-factor authentication, replacing a console log action previously triggered upon success. The change enhances the authentication flow by redirecting users to a specified path upon validation. Additionally, minor refactorings are done such as replacing direct routing paths with path configs and adjusting import statements.
This commit is contained in:
giancarlo
2024-03-27 14:30:23 +08:00
parent 2acd9c7d10
commit f0883c19ef
5 changed files with 34 additions and 17 deletions

View File

@@ -1,9 +1,12 @@
import Link from 'next/link';
import { redirect } from 'next/navigation'; import { redirect } from 'next/navigation';
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert'; import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
import { Button } from '@kit/ui/button'; import { Button } from '@kit/ui/button';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
import pathsConfig from '~/config/paths.config';
interface Params { interface Params {
searchParams: { searchParams: {
error: string; error: string;
@@ -15,7 +18,7 @@ function AuthCallbackErrorPage({ searchParams }: Params) {
// if there is no error, redirect the user to the sign-in page // if there is no error, redirect the user to the sign-in page
if (!error) { if (!error) {
redirect('/auth/sign-in'); redirect(pathsConfig.auth.signIn);
} }
return ( return (
@@ -32,15 +35,11 @@ function AuthCallbackErrorPage({ searchParams }: Params) {
</Alert> </Alert>
</div> </div>
<ResendLinkForm /> <Button>
<Link href={pathsConfig.auth.signIn}>
<div className={'flex flex-col space-y-2'}> <Trans i18nKey={'auth:signIn'} />
<Button variant={'ghost'}> </Link>
<a href={'/auth/sign-in'}> </Button>
<Trans i18nKey={'auth:signIn'} />
</a>
</Button>
</div>
</div> </div>
); );
} }

View File

@@ -37,6 +37,7 @@ function SignUpPage({ searchParams }: Props) {
providers={authConfig.providers} providers={authConfig.providers}
paths={{ paths={{
callback: pathsConfig.auth.callback, callback: pathsConfig.auth.callback,
appHome: pathsConfig.app.home,
}} }}
inviteToken={inviteToken} inviteToken={inviteToken}
/> />

View File

@@ -8,6 +8,12 @@ import pathsConfig from '~/config/paths.config';
import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
import { withI18n } from '~/lib/i18n/with-i18n'; import { withI18n } from '~/lib/i18n/with-i18n';
interface Props {
searchParams: {
next?: string;
};
}
export const generateMetadata = async () => { export const generateMetadata = async () => {
const i18n = await createI18nServerInstance(); const i18n = await createI18nServerInstance();
@@ -16,7 +22,7 @@ export const generateMetadata = async () => {
}; };
}; };
async function VerifyPage() { async function VerifyPage(props: Props) {
const client = getSupabaseServerComponentClient(); const client = getSupabaseServerComponentClient();
const needsMfa = await checkRequiresMultiFactorAuthentication(client); const needsMfa = await checkRequiresMultiFactorAuthentication(client);
@@ -24,10 +30,12 @@ async function VerifyPage() {
redirect(pathsConfig.auth.signIn); redirect(pathsConfig.auth.signIn);
} }
const redirectPath = props.searchParams.next ?? pathsConfig.app.home;
return ( return (
<MultiFactorChallengeContainer <MultiFactorChallengeContainer
onSuccess={() => { paths={{
console.log('2'); redirectPath,
}} }}
/> />
); );

View File

@@ -3,6 +3,8 @@
import type { FormEventHandler } from 'react'; import type { FormEventHandler } from 'react';
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import { useMutation } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import useFetchAuthFactors from '@kit/supabase/hooks/use-fetch-mfa-factors'; import useFetchAuthFactors from '@kit/supabase/hooks/use-fetch-mfa-factors';
@@ -17,14 +19,22 @@ import Spinner from '@kit/ui/spinner';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
export function MultiFactorChallengeContainer({ export function MultiFactorChallengeContainer({
onSuccess, paths,
}: React.PropsWithChildren<{ }: React.PropsWithChildren<{
onSuccess: () => void; paths: {
redirectPath: string;
};
}>) { }>) {
const router = useRouter();
const [factorId, setFactorId] = useState(''); const [factorId, setFactorId] = useState('');
const [verifyCode, setVerifyCode] = useState(''); const [verifyCode, setVerifyCode] = useState('');
const verifyMFAChallenge = useVerifyMFAChallenge(); const verifyMFAChallenge = useVerifyMFAChallenge();
const onSuccess = useCallback(() => {
router.replace(paths.redirectPath);
}, [router, paths.redirectPath]);
const onSubmitClicked: FormEventHandler<HTMLFormElement> = useCallback( const onSubmitClicked: FormEventHandler<HTMLFormElement> = useCallback(
(event) => { (event) => {
void (async () => { void (async () => {

View File

@@ -2,8 +2,7 @@
import type { Provider } from '@supabase/supabase-js'; import type { Provider } from '@supabase/supabase-js';
import { isBrowser } from '@supabase/ssr'; import { isBrowser } from '@kit/shared/utils';
import { Divider } from '@kit/ui/divider'; import { Divider } from '@kit/ui/divider';
import { If } from '@kit/ui/if'; import { If } from '@kit/ui/if';