Skip to main content
Device registration protects your users from account takeovers by requiring verification when they sign in from an unrecognized device. For a general overview of the feature, see Device Registration.

Prerequisites

  • You need to have the Dynamic client initialized.
  • You need to have device registration enabled in your environment’s settings in the Dynamic Dashboard.
  • You need to have universal links configured for your app.
  • React Native SDK v5 or later.

Using our UI

Device registration is handled automatically by the SDK. When a user signs in from an unrecognized device, the SDK displays a security prompt with the user’s email, asking them to verify the device. Once the user taps the verification link in their email, the SDK detects the deep link, completes registration, and dismisses the prompt automatically. No additional code is needed — just enable device registration in your dashboard.

Using your UI

To build a custom device registration experience, disable the built-in modal in your client configuration:
React Native
import { createClient } from '@dynamic-labs/client';

const client = createClient({
  environmentId: 'YOUR_ENVIRONMENT_ID',
  deviceRegistrationModal: { enabled: false },
});

Checking if device registration is required

Listen for authenticated user changes and check if the user’s scopes include device:register.
React Native
import { dynamicClient } from '<path to client file>';
import { useEffect, useState } from 'react';
import { View, Text } from 'react-native';

const DeviceRegistrationBanner = () => {
  const [showBanner, setShowBanner] = useState(false);

  useEffect(() => {
    const handleAuthenticatedUserChanged = (user) => {
      if (user.scopes.includes('device:register')) {
        setShowBanner(true);
      }
    };

    dynamicClient.auth.on('authenticatedUserChanged', handleAuthenticatedUserChanged);

    return () => {
      dynamicClient.auth.off('authenticatedUserChanged', handleAuthenticatedUserChanged);
    };
  }, [dynamicClient]);

  if (!showBanner) return null;

  return (
    <View>
      <Text>Please check your email to verify this device.</Text>
    </View>
  );
};

Handling device registration completion

The SDK handles the universal link redirect and device registration completion automatically, even when the built-in modal is disabled. You can listen for completion to update your UI:
React Native
import { dynamicClient } from '<path to client file>';
import { useEffect } from 'react';

const useDeviceRegistrationCompleted = (callback: () => void) => {
  useEffect(() => {
    dynamicClient.deviceRegistration.on('deviceRegistrationCompleted', callback);

    return () => {
      dynamicClient.deviceRegistration.off('deviceRegistrationCompleted', callback);
    };
  }, []);
};

Getting registered devices

Retrieve all trusted devices for the current user. Each device includes a pre-parsed displayText and type for easy display. Each device includes:
FieldTypeDescription
idstringThe device registration ID
createdAtstringISO date of when the device was registered
displayTextstring | nullA friendly device name (e.g., “iPhone”)
type'mobile' | 'desktop' | nullThe device type
isCurrentDevicebooleanWhether this is the device making the request
React Native
import { dynamicClient } from '<path to client file>';
import { useEffect, useState } from 'react';
import { View, Text, FlatList } from 'react-native';
import { RegisteredDevice } from '@dynamic-labs/client';

const RegisteredDevices = () => {
  const [devices, setDevices] = useState<RegisteredDevice[]>([]);

  useEffect(() => {
    dynamicClient.deviceRegistration.getRegisteredDevices().then(setDevices);
  }, []);

  return (
    <FlatList
      data={devices}
      keyExtractor={(device) => device.id}
      renderItem={({ item: device }) => (
        <View>
          <Text>
            {device.displayText ?? 'Unknown device'}
            {device.isCurrentDevice && ' (this device)'}
          </Text>
        </View>
      )}
    />
  );
};

Revoking a device

Remove a single trusted device. If the revoked device is the current device, the user will be logged out.
React Native
import { dynamicClient } from '<path to client file>';

const handleRevoke = async (deviceRegistrationId: string) => {
  await dynamicClient.deviceRegistration.revokeRegisteredDevice({ deviceRegistrationId });
};

Revoking all devices

Remove all trusted devices for the current user. This always logs the user out.
React Native
import { dynamicClient } from '<path to client file>';

const handleRevokeAll = async () => {
  await dynamicClient.deviceRegistration.revokeAllRegisteredDevices();
};