diff --git a/apps/studio/components/interfaces/SignIn/SignInForm.tsx b/apps/studio/components/interfaces/SignIn/SignInForm.tsx index 6409890cdac..bf0549a81c4 100644 --- a/apps/studio/components/interfaces/SignIn/SignInForm.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInForm.tsx @@ -81,7 +81,7 @@ export const SignInForm = () => { if (data) { if (data.currentLevel !== data.nextLevel) { toast.success(`You need to provide your second factor authentication`, { id: toastId }) - const url = buildPathWithParams('/sign-in-mfa') + const url = buildPathWithParams('/sign-in-mfa?method=email') router.replace(url) return } diff --git a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx index 2b437c0f802..934998d089a 100644 --- a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx @@ -1,7 +1,7 @@ import { zodResolver } from '@hookform/resolvers/zod' import type { Factor } from '@supabase/supabase-js' import { useQueryClient } from '@tanstack/react-query' -import { useAuthError } from 'common' +import { useAuthError, useParams } from 'common' import { Lock } from 'lucide-react' import Link from 'next/link' import { useRouter } from 'next/router' @@ -13,10 +13,12 @@ import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import z from 'zod' import { AlertError } from '@/components/ui/AlertError' +import { useAddLoginEvent } from '@/data/misc/audit-login-mutation' import { useMfaChallengeAndVerifyMutation } from '@/data/profile/mfa-challenge-and-verify-mutation' import { useMfaListFactorsQuery } from '@/data/profile/mfa-list-factors-query' import { useSignOut } from '@/lib/auth' import { getReturnToPath } from '@/lib/gotrue' +import { useTrack } from '@/lib/telemetry/track' const schema = z.object({ code: z.string().min(1, 'MFA Code is required'), @@ -39,6 +41,10 @@ export const SignInMfaForm = ({ context = 'sign-in' }: SignInMfaFormProps) => { const router = useRouter() const signOut = useSignOut() const queryClient = useQueryClient() + const { method: signInMethod = 'unknown' } = useParams() + + const track = useTrack() + const { mutate: addLoginEvent } = useAddLoginEvent() const [selectedFactor, setSelectedFactor] = useState(null) const form = useForm>({ @@ -61,6 +67,11 @@ export const SignInMfaForm = ({ context = 'sign-in' }: SignInMfaFormProps) => { isSuccess, } = useMfaChallengeAndVerifyMutation({ onSuccess: async () => { + if (context === 'sign-in') { + track('sign_in', { category: 'account', method: signInMethod }) + addLoginEvent({}) + } + await queryClient.resetQueries() if (context === 'forgot-password') { diff --git a/apps/studio/components/interfaces/SignIn/SignInPartner.tsx b/apps/studio/components/interfaces/SignIn/SignInPartner.tsx index 6aafa0281d8..5c792b80129 100644 --- a/apps/studio/components/interfaces/SignIn/SignInPartner.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInPartner.tsx @@ -21,7 +21,7 @@ export const SignInPartner = () => { try { await auth.signInWithIdToken({ provider: partner, token }) } finally { - router.replace({ pathname: '/sign-in-mfa' }) + router.replace({ pathname: '/sign-in-mfa', query: { method: partner } }) } } else { router.replace({ pathname: '/sign-in' }) diff --git a/packages/common/telemetry-constants.ts b/packages/common/telemetry-constants.ts index 12dad4e2243..2b7ff3134ac 100644 --- a/packages/common/telemetry-constants.ts +++ b/packages/common/telemetry-constants.ts @@ -46,14 +46,16 @@ export interface SignUpEvent { } /** - * Triggered when a user signs in with GitHub, Email and Password or SSO. + * Triggered when a user signs in with an OAuth provider, Email and Password, or SSO. * * Some unintuitive behavior: * - If signing up with GitHub the SignInEvent gets triggered first before the SignUpEvent. + * - Captured server-side; the distinct_id often resolves to the anonymous cookie because + * the event races identify, so don't use it as a funnel join key across the auth boundary. * * @group Events * @source studio - * @page /sign-in-mfa + * @page /sign-in, /sign-in-mfa */ export interface SignInEvent { action: 'sign_in'