diff --git a/nextjs/src/app/api/Auth.ts b/nextjs/src/app/api/Auth.ts index 9e0ad3114..bf5ec9318 100644 --- a/nextjs/src/app/api/Auth.ts +++ b/nextjs/src/app/api/Auth.ts @@ -21,6 +21,7 @@ export interface IUserSignInData { email: string | undefined isPasskey: boolean password?: string + isPassword?: boolean } export interface IEmailVerifyData { verificationCode: string diff --git a/nextjs/src/features/auth/components/user-auth-form.tsx b/nextjs/src/features/auth/components/user-auth-form.tsx index c9f3905cd..f33eab8a3 100644 --- a/nextjs/src/features/auth/components/user-auth-form.tsx +++ b/nextjs/src/features/auth/components/user-auth-form.tsx @@ -18,22 +18,17 @@ import { passwordEncryption, } from '@/app/api/Auth' import React, { useState } from 'react' -import { - generateAuthenticationOption, - verifyAuthentication, -} from '@/app/api/Fido' -import { setRefreshToken, setToken } from '@/lib/authSlice' +import { signIn, useSession } from 'next-auth/react' import { AlertComponent } from '@/components/AlertComponent' import { AxiosResponse } from 'axios' import { Button } from '@/components/ui/button' -import { IVerifyRegistrationObj } from '@/components/profile/interfaces' import { Icons } from '@/config/svgs/Auth' import { Input } from '@/components/ui/input' import Link from 'next/link' import { apiStatusCodes } from '@/config/CommonConstant' +import { generateAuthenticationOption } from '@/app/api/Fido' import { setProfile } from '@/lib/profileSlice' -import { signIn } from 'next-auth/react' import { startAuthentication } from '@simplewebauthn/browser' import { useDispatch } from 'react-redux' import { useForm } from 'react-hook-form' @@ -61,6 +56,7 @@ export default function SignInViewPage(): React.JSX.Element { const [alert, setAlert] = useState(null) const [success, setSuccess] = useState(null) + const { data: session } = useSession() const dispatch = useDispatch() const route = useRouter() const signInForm = useForm({ @@ -77,7 +73,7 @@ export default function SignInViewPage(): React.JSX.Element { ): Promise< | { role: { name: string } - orgId: string + orgId: string | null } | undefined > => { @@ -87,10 +83,11 @@ export default function SignInViewPage(): React.JSX.Element { const { data } = response as AxiosResponse if (data?.data?.userOrgRoles?.length > 0) { - const role = data?.data?.userOrgRoles.find( - (item: { orgRole: { name: PlatformRoles } }) => + const platformAdminRole = data?.data?.userOrgRoles.find( + (item: { orgRole: { name: string } }) => item.orgRole.name === PlatformRoles.platformAdmin, ) + const selectedRole = platformAdminRole || data?.data?.userOrgRoles[0] const permissionArray: string[] = [] data?.data?.userOrgRoles?.forEach( @@ -114,16 +111,16 @@ export default function SignInViewPage(): React.JSX.Element { const orgId = orgWithValidId?.orgId ?? null return { - role: role?.orgRole ?? '', + role: { name: selectedRole.orgRole.name }, orgId, } } else { - // eslint-disable-next-line no-console console.error('No roles found for the user') + return undefined } } catch (error) { - // eslint-disable-next-line no-console console.error('Error fetching user details', error) + return undefined } } @@ -137,6 +134,7 @@ export default function SignInViewPage(): React.JSX.Element { email: values.email, password: await passwordEncryption(values.password || ''), isPasskey: false, + isPassword: isPasswordTab, } : { email: values.email, @@ -165,19 +163,6 @@ export default function SignInViewPage(): React.JSX.Element { } } - const verifyAuthenticationMethod = async ( - verifyAuthenticationObj: IVerifyRegistrationObj, - userData: { userName: string }, - ): Promise => { - try { - const res = verifyAuthentication(verifyAuthenticationObj, userData) - return await res - } catch (error) { - setFidoLoader(false) - throw error - } - } - const authenticateWithPasskey = async (email: string): Promise => { try { setLoading(true) @@ -208,21 +193,23 @@ export default function SignInViewPage(): React.JSX.Element { ...attResp, challangeId: challengeId, } + const entityData = { + verifyAuthenticationObj: JSON.stringify(verifyAuthenticationObj), + obj: JSON.stringify(obj), + isPasswordTab, + } - const verificationResp = await verifyAuthenticationMethod( - verifyAuthenticationObj, - obj, - ) - const { data } = verificationResp as AxiosResponse - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const token = data?.data?.access_token - const refreshToken = data?.data?.refresh_token - - dispatch(setToken(token)) - dispatch(setRefreshToken(refreshToken)) + const verificationResp = await signIn('credentials', { + ...entityData, + redirect: false, + callbackUrl: '/dashboard', + }) - const userRole = await getUserDetails(token) + if (verificationResp?.ok && verificationResp?.status === 200) { + if (!session?.accessToken) { + return + } + const userRole = await getUserDetails(session?.accessToken) if (!userRole?.role?.name) { setAlert('Invalid user role') @@ -234,8 +221,8 @@ export default function SignInViewPage(): React.JSX.Element { ? '/dashboard/settings' : '/dashboard', ) - } else if (data?.error) { - setFidoUserError(data?.error) + } else if (verificationResp?.error) { + setFidoUserError(verificationResp?.error) } else { setFidoUserError('Something went wrong during verification') } diff --git a/nextjs/src/utils/authOptions.ts b/nextjs/src/utils/authOptions.ts index 475f36b0b..60587f160 100644 --- a/nextjs/src/utils/authOptions.ts +++ b/nextjs/src/utils/authOptions.ts @@ -7,6 +7,10 @@ import { Provider } from 'next-auth/providers/index' import { apiRoutes } from '@/config/apiRoutes' import { envConfig } from '@/config/envConfig' +type PasskeyUser = { + userName: string + email?: string +} interface MyAuthOptions { providers: Provider[] callbacks?: { @@ -41,28 +45,70 @@ export const authOptions: MyAuthOptions = { }, password: { label: 'Password', type: 'password' }, isPasskey: { label: 'IsPasskey', type: 'boolean' }, + isPassword: { label: 'isPassword', type: 'boolean' }, + obj: { label: 'obj', type: 'string' }, + verifyAuthenticationObj: { + label: 'verifyAuthenticationObj', + type: 'string', + }, }, async authorize(credentials) { + let parsedVerifyAuthObj: Record = {} + let parsedObj: PasskeyUser = { userName: '' } try { - const { email, password, isPasskey } = credentials || {} - - const sanitizedPayload = { + const { email, password, isPasskey, + isPassword, + verifyAuthenticationObj, + obj, + } = credentials || {} + let sanitizedPayload = {} + if (isPassword) { + sanitizedPayload = { + email, + password, + isPasskey, + } + } else { + try { + parsedVerifyAuthObj = JSON.parse(verifyAuthenticationObj || '{}') + parsedObj = JSON.parse(obj || '{}') + } catch (err) { + console.error('Failed to parse incoming JSON strings:', err) + return null + } + sanitizedPayload = { + ...parsedVerifyAuthObj, + } + } + // eslint-disable-next-line init-declarations + let res + if (isPassword) { + res = await fetch( + `${envConfig.NEXT_PUBLIC_BASE_URL}${apiRoutes.auth.sinIn}`, + { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(sanitizedPayload), + }, + ) + } else { + if (obj) { + res = await fetch( + `${envConfig.NEXT_PUBLIC_BASE_URL}/${apiRoutes.auth.fidoVerifyAuthentication}${parsedObj.userName}`, + { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(sanitizedPayload), + }, + ) + } } - const res = await fetch( - `${envConfig.NEXT_PUBLIC_BASE_URL}${apiRoutes.auth.sinIn}`, - { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(sanitizedPayload), - }, - ) - - if (!res.ok) { - console.error('Error fetching user:', res.statusText) + if (!res?.ok) { + console.error('Error fetching user:', res?.statusText) return null }