Skip to content

Commit

Permalink
fix: simplify MFA setup
Browse files Browse the repository at this point in the history
  • Loading branch information
schmanu committed Oct 9, 2023
1 parent 42d66f2 commit b0f2238
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 52 deletions.
32 changes: 7 additions & 25 deletions src/components/settings/SignerAccountMFA/PasswordForm.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,33 @@
import { DeviceShareRecovery } from '@/hooks/wallets/mpc/recovery/DeviceShareRecovery'
import { SecurityQuestionRecovery } from '@/hooks/wallets/mpc/recovery/SecurityQuestionRecovery'
import { Typography, TextField, FormControlLabel, Checkbox, Button, Box } from '@mui/material'
import { Typography, TextField, Button, Box } from '@mui/material'
import { type Web3AuthMPCCoreKit } from '@web3auth/mpc-core-kit'
import { useState, useMemo } from 'react'
import { Controller, useForm } from 'react-hook-form'
import { useForm } from 'react-hook-form'
import { enableMFA } from './helper'

enum PasswordFieldNames {
oldPassword = 'oldPassword',
newPassword = 'newPassword',
confirmPassword = 'confirmPassword',
storeDeviceShare = 'storeDeviceShare',
}

type PasswordFormData = {
[PasswordFieldNames.oldPassword]: string | undefined
[PasswordFieldNames.newPassword]: string
[PasswordFieldNames.confirmPassword]: string
[PasswordFieldNames.storeDeviceShare]: boolean
}

export const PasswordForm = ({ mpcCoreKit }: { mpcCoreKit: Web3AuthMPCCoreKit }) => {
const formMethods = useForm<PasswordFormData>({
mode: 'all',
defaultValues: async () => {
const isDeviceShareStored = await new DeviceShareRecovery(mpcCoreKit).isEnabled()
return {
[PasswordFieldNames.confirmPassword]: '',
[PasswordFieldNames.oldPassword]: undefined,
[PasswordFieldNames.newPassword]: '',
[PasswordFieldNames.storeDeviceShare]: isDeviceShareStored,
}
defaultValues: {
[PasswordFieldNames.confirmPassword]: '',
[PasswordFieldNames.oldPassword]: undefined,
[PasswordFieldNames.newPassword]: '',
},
})

const { register, formState, getValues, control, handleSubmit } = formMethods
const { register, formState, getValues, handleSubmit } = formMethods

const [enablingMFA, setEnablingMFA] = useState(false)

Expand Down Expand Up @@ -100,17 +93,6 @@ export const PasswordForm = ({ mpcCoreKit }: { mpcCoreKit: Web3AuthMPCCoreKit })
})}
/>

<Controller
control={control}
name={PasswordFieldNames.storeDeviceShare}
render={({ field: { value, ...field } }) => (
<FormControlLabel
control={<Checkbox checked={value ?? false} {...field} />}
label="Do not ask for second factor on this device"
/>
)}
/>

<Button
sx={{ justifySelf: 'flex-start' }}
disabled={!formMethods.formState.isValid || enablingMFA}
Expand Down
28 changes: 1 addition & 27 deletions src/components/settings/SignerAccountMFA/helper.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { DeviceShareRecovery } from '@/hooks/wallets/mpc/recovery/DeviceShareRecovery'
import { SecurityQuestionRecovery } from '@/hooks/wallets/mpc/recovery/SecurityQuestionRecovery'
import { logError } from '@/services/exceptions'
import ErrorCodes from '@/services/exceptions/ErrorCodes'
import { asError } from '@/services/exceptions/utils'
import { getPubKeyPoint } from '@tkey-mpc/common-types'
import { type Web3AuthMPCCoreKit } from '@web3auth/mpc-core-kit'
import BN from 'bn.js'

export const isMFAEnabled = (mpcCoreKit: Web3AuthMPCCoreKit) => {
if (!mpcCoreKit) {
Expand All @@ -20,49 +17,26 @@ export const enableMFA = async (
{
newPassword,
oldPassword,
storeDeviceShare,
}: {
newPassword: string
oldPassword: string | undefined
storeDeviceShare: boolean
},
) => {
if (!mpcCoreKit) {
return
}
const securityQuestions = new SecurityQuestionRecovery(mpcCoreKit)
const deviceShareRecovery = new DeviceShareRecovery(mpcCoreKit)
try {
// 1. setup device factor with password recovery
await securityQuestions.upsertPassword(newPassword, oldPassword)
const securityQuestionFactor = await securityQuestions.recoverWithPassword(newPassword)
if (!securityQuestionFactor) {
throw Error('Could not recover using the new password recovery')
}
// We commit the new password separately
// It is necessary to be able to input the password factor before removing the (active) device factor
await mpcCoreKit.commitChanges()

if (!isMFAEnabled(mpcCoreKit)) {
// 2. enable MFA in mpcCoreKit
const recoveryFactor = await mpcCoreKit.enableMFA({})

// 3. remove the recovery factor the mpcCoreKit creates
const recoverKey = new BN(recoveryFactor, 'hex')
const recoverPubKey = getPubKeyPoint(recoverKey)
await mpcCoreKit.deleteFactor(recoverPubKey, recoverKey)
}

const hasDeviceShare = await deviceShareRecovery.isEnabled()

if (!hasDeviceShare && storeDeviceShare) {
await deviceShareRecovery.createAndStoreDeviceFactor()
}

if (hasDeviceShare && !storeDeviceShare) {
// Switch to password recovery factor such that we can delete the device factor
await mpcCoreKit.inputFactorKey(new BN(securityQuestionFactor, 'hex'))
await deviceShareRecovery.removeDeviceFactor()
await mpcCoreKit.enableMFA({}, false)
}

await mpcCoreKit.commitChanges()
Expand Down

0 comments on commit b0f2238

Please sign in to comment.