Skip to main content

Deleting a device

Users might need to delete an MFA device if it’s lost or replaced. To do so, first authenticate with the device, then use the deleteUserDevice function. Delete a TOTP device with TOTP code:
import React, { useState } from 'react';
import { Alert, View, TextInput, Button } from 'react-native';
import { useDynamic } from './path-to-your-client';

export function DeleteMfaDevice({ deviceId }: { deviceId: string }) {
  const client = useDynamic();
  const [code, setCode] = useState('');
  const [loading, setLoading] = useState(false);

  const handleDeleteDevice = async () => {
    if (!code.trim()) {
      Alert.alert('Error', 'Please enter the verification code');
      return;
    }

    try {
      setLoading(true);
      // First, authenticate with the device to create MFA token
      const mfaAuthToken = await client.mfa.authenticateDevice({
        code,
        deviceId,
        createMfaToken: { singleUse: true }
      });

      if (!mfaAuthToken) {
        Alert.alert('Error', 'Failed to authenticate device');
        return;
      }

      // Then, delete the device using the token
      await client.mfa.deleteUserDevice(deviceId, mfaAuthToken);
      Alert.alert('Success', 'MFA device deleted successfully');
    } catch (error) {
      console.error('Failed to delete MFA device:', error);
      Alert.alert('Error', 'Failed to delete MFA device');
    } finally {
      setLoading(false);
    }
  };

  return (
    <View>
      <TextInput
        placeholder="Enter 6-digit code"
        value={code}
        onChangeText={setCode}
        keyboardType="numeric"
        maxLength={6}
      />
      <Button
        title="Delete Device"
        onPress={handleDeleteDevice}
        disabled={loading}
      />
    </View>
  );
}
Delete a TOTP device with recovery code:
import React, { useState } from 'react';
import { Alert, View, TextInput, Button } from 'react-native';
import { useDynamic } from './path-to-your-client';

export function DeleteMfaDeviceWithRecovery({ deviceId }: { deviceId: string }) {
  const client = useDynamic();
  const [recoveryCode, setRecoveryCode] = useState('');
  const [loading, setLoading] = useState(false);

  const handleDeleteDevice = async () => {
    if (!recoveryCode.trim()) {
      Alert.alert('Error', 'Please enter the recovery code');
      return;
    }

    try {
      setLoading(true);
      // First, authenticate with recovery code to create MFA token
      const mfaAuthToken = await client.mfa.authenticateRecoveryCode({
        code: recoveryCode,
        createMfaToken: { singleUse: true }
      });

      if (!mfaAuthToken) {
        Alert.alert('Error', 'Failed to authenticate recovery code');
        return;
      }

      // Then, delete the device using the token
      await client.mfa.deleteUserDevice(deviceId, mfaAuthToken);
      Alert.alert('Success', 'MFA device deleted successfully');
    } catch (error) {
      console.error('Failed to delete MFA device:', error);
      Alert.alert('Error', 'Failed to delete MFA device');
    } finally {
      setLoading(false);
    }
  };

  return (
    <View>
      <TextInput
        placeholder="Enter recovery code"
        value={recoveryCode}
        onChangeText={setRecoveryCode}
      />
      <Button
        title="Delete Device"
        onPress={handleDeleteDevice}
        disabled={loading}
      />
    </View>
  );
}
Delete a passkey:
import React, { useState } from 'react';
import { Alert, View, Button } from 'react-native';
import { dynamicClient } from './path-to-your-client';

export function DeletePasskey({ passkeyId }: { passkeyId: string }) {
  const [loading, setLoading] = useState(false);

  const handleDeletePasskey = async () => {
    try {
      setLoading(true);
      await dynamicClient.passkeys.delete({ passkeyId });
      Alert.alert('Success', 'Passkey deleted successfully');
    } catch (error) {
      console.error('Failed to delete passkey:', error);
      Alert.alert('Error', 'Failed to delete passkey');
    } finally {
      setLoading(false);
    }
  };

  return (
    <View>
      <Button
        title="Delete Passkey"
        onPress={handleDeletePasskey}
        disabled={loading}
      />
    </View>
  );
}

Admin Reset

If a user loses all their devices and recovery codes, an admin can reset their MFA from the Dynamic dashboard.
  1. Go to the Users page in the Dynamic Dashboard.
  2. Find the user and open their detail panel.
  3. In the Security section, click Reset MFA.
  4. Confirm the action.
This removes all MFA devices from the user’s account, letting them set up a new device on their next login.