---
title: Device self-service in React Native apps
description: Learn how to manage user authentication devices, such as renaming or deleting them, in your React Native applications using the Ping Identity SDK.
component: orchsdks
page_id: orchsdks:journey:use-cases/device-self-service/react-native-device-self-service
canonical_url: https://developer.pingidentity.com/orchsdks/journey/use-cases/device-self-service/react-native-device-self-service.html
llms_txt: https://developer.pingidentity.com/orchsdks/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: Mon, 01 Jun 2026 16:09:20 +0100
keywords: ["PingOne Advanced Identity Cloud", "PingAM", "Journeys", "React Native", "Device Management", "MFA", "FIDO", "WebAuthn", "OATH", "Push", "SDK"]
section_ids:
  react-native_device-profile_modules: Installing modules
  initializing_the_device_client: Initializing the device client
  listing_registered_devices: Listing registered devices
  renaming_devices: Renaming devices
  deleting_devices: Deleting devices
  handling_errors: Handling errors
---

# Device self-service in React Native apps

[icon: circle-check, set=far]PingOne Advanced Identity Cloud [icon: circle-check, set=far]PingAM [icon: react, set=fab]React Native

The **Device Client** module for React Native provides a comprehensive and unified API for managing Multi-Factor Authentication (MFA) devices and user profile devices registered with Advanced Identity Cloud or PingAM servers.

The module simplifies the process of retrieving, updating, and deleting various types of authentication devices, enabling you to build secure and user-friendly device management experiences within your React Native applications.

## Installing modules

To install the module into your React Native project, use `yarn` or `npm` as follows:

* yarn

* npm

```shell
yarn add @ping-identity/rn-device-client
```

```shell
npm install @ping-identity/rn-device-client
```

After installation, import the module as follows:

```typescript
import { createDeviceClient } from '@ping-identity/rn-device-client';
```

## Initializing the device client

The **Device Client** module uses the REST-based device management endpoints provided by Advanced Identity Cloud and PingAM.

The module requires a session token when making calls to the device management endpoints. In a React Native app, you must obtain the SSO token explicitly and pass it to the device client.

Session tokens often have a short duration and may expire after 5 minutes. If the client does not have an active session token, trigger an authentication journey to obtain a new one before attempting to manage registered devices.

Call `createDeviceClient()` after authenticating a user and obtaining their session token:

Initializing a device client on React Native

```javascript
import { useJourney } from '@ping-identity/rn-journey';
import { createDeviceClient } from '@ping-identity/rn-device-client';
import type { JourneyClient } from '@ping-identity/rn-journey';

const [, journeyActions] = useJourney(journeyClient);

async function loadDevices() {
  const token = await journeyActions.ssoToken();
  if (!token) {
    // No active session — redirect to login
    return;
  }

  const deviceClient = createDeviceClient({
    serverUrl: 'https://openam-forgerock-sdks.forgeblocks.com/am',
    ssoToken: token.value,
    realm: 'alpha',
    cookieName: 'ch15fefc5407912',
  });

  try {
    const devices = await deviceClient.oath.get();
    // use devices
  } catch (error) {
    // Token may have expired. Re-authenticate and retry
    console.error('Failed to fetch devices:', error);
  } finally {
    await deviceClient.dispose();
  }
}
```

The configuration properties for the device client are as follows:

**Device client parameters on React Native**

| Parameter                   | Description                                                                                                                                                                                                                                                                                                                                                           | Required? |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| `serverUrl` (*String*)      | The base URL of your server, including the access management path.- PingOne Advanced Identity Cloud example

  `https://openam-forgerock-sdks.forgeblocks.com/am`

- PingAM example

  `https://openam.example.com:8443/openam`                                                                                                                                       | Yes       |
| `ssoToken` (*String*)       | The SSO token for the authenticated user.Obtain this by calling `journeyActions.ssoToken()` after a successful Journey.Learn more in [Managing sessions and tokens in React Native](../../usage/react-native/06-handling-sessions.html).                                                                                                                              | Yes       |
| `realm` (*String*)          | The authentication realm.- PingOne Advanced Identity Cloud example

  `alpha`

- PingAM example

  `root`                                                                                                                                                                                                                                                             | Yes       |
| `cookieName` (*String*)     | The name of the SSO cookie configured on the server.For example, PingAM servers use `iPlanetDirectoryPro`> **Collapse: How do I find my PingOne Advanced Identity Cloud cookie name?**
>
> To locate the cookie name in an PingOne Advanced Identity Cloud tenant:
>
> 1. Navigate to Tenant settings > Global Settings
>
> 2. Copy the value of the Cookie property. | Yes       |
| `logger` (*LoggerInstance*) | Optional logger instance created by `@ping-identity/rn-logger`.Learn more in [Configuring logging in React Native](../../customization/logging/react-native-custom-logging.html).                                                                                                                                                                                     | No        |

## Listing registered devices

For each type of registered device, call the `get()` method to retrieve the list from the server.

The available device types are as follows:

| Registered device type          | Listing method                |
| ------------------------------- | ----------------------------- |
| WebAuthn / FIDO2 authenticators | `deviceClient.webAuthn.get()` |
| Bound devices                   | `deviceClient.bound.get()`    |
| Device profiles                 | `deviceClient.profile.get()`  |
| Push MFA devices                | `deviceClient.push.get()`     |
| OATH MFA devices (TOTP / HOTP)  | `deviceClient.oath.get()`     |

Each method returns a Promise. Different device types return different information you can display to the user, such as the device name or last access date.

The following code shows how to obtain lists of the different devices from the server:

* WebAuthn / FIDO

* Bound devices

* Profiled devices

* Push devices

* OATH devices

Listing WebAuthn devices on React Native

```typescript
const devices = await deviceClient.webAuthn.get();

devices.forEach((device) => {
    console.log('id:', device.id);
    console.log('deviceName:', device.deviceName);
    console.log('uuid:', device.uuid);
    console.log('createdDate:', new Date(device.createdDate).toISOString());
    console.log('lastAccessDate:', new Date(device.lastAccessDate).toISOString());
    console.log('credentialId:', device.credentialId);
    console.log('---');
  });
```

Listing bound devices on React Native

```typescript
const devices = await deviceClient.bound.get();

  devices.forEach((device) => {
    console.log('id:           ', device.id);
    console.log('deviceName:   ', device.deviceName);
    console.log('uuid:         ', device.uuid);
    console.log('deviceId:     ', device.deviceId);
    console.log('createdDate:  ', new Date(device.createdDate).toISOString());
    console.log('lastAccessDate:', new Date(device.lastAccessDate).toISOString());
    console.log('---');
  });
```

Listing profiled devices on React Native

```typescript
const devices = await deviceClient.profile.get();

  devices.forEach((device) => {
    console.log('id:               ', device.id);
    console.log('deviceName:       ', device.deviceName);
    console.log('identifier:       ', device.identifier);
    console.log('metadata:         ', JSON.stringify(device.metadata, null, 2));
    console.log('location:         ', device.location
      ? `lat ${device.location.latitude}, lon ${device.location.longitude}`
      : 'none');
    console.log('lastSelectedDate: ', new Date(device.lastSelectedDate).toISOString());
    console.log('---');
  });
```

Listing Push devices on React Native

```typescript
const devices = await deviceClient.push.get();

  devices.forEach((device) => {
    console.log('id:           ', device.id);
    console.log('deviceName:   ', device.deviceName);
    console.log('uuid:         ', device.uuid);
    console.log('createdDate:  ', new Date(device.createdDate).toISOString());
    console.log('lastAccessDate:', new Date(device.lastAccessDate).toISOString());
    console.log('---');
  });
```

Listing OATH devices on React Native

```typescript
const devices = await deviceClient.oath.get();

  devices.forEach((device) => {
    console.log('id:           ', device.id);
    console.log('deviceName:   ', device.deviceName);
    console.log('uuid:         ', device.uuid);
    console.log('createdDate:  ', new Date(device.createdDate).toISOString());
    console.log('lastAccessDate:', new Date(device.lastAccessDate).toISOString());
    console.log('---');
  });
```

## Renaming devices

Use the `update()` method to rename a registered device and save the change to the server.

Obtain the device object from `get()`, set the new `deviceName`, and pass it to `update()`. `update()` returns a `Promise` that resolves with the updated device object.

* Bound devices

* OATH devices

Renaming a bound device on React Native

```typescript
const devices = await deviceClient.bound.get();
const device = devices[0];

const updatedDevice = await deviceClient.bound.update({
  ...device,
  deviceName: 'My Updated Device Name',
});

console.log('Updated bound device:', updatedDevice);
```

Renaming OATH devices on React Native

```typescript
const devices = await deviceClient.oath.get();
const device = devices[0];

const updatedDevice = await deviceClient.oath.update({
  ...device,
  deviceName: 'Work Authenticator',
});

console.log('Updated OATH device:', updatedDevice);
```

## Deleting devices

Use the `delete()` method to delete a device from the user's profile.

The authentication journey that provided the user's session must meet one or more of the following criteria:

* Used the same multi-factor authentication method as the device you want to delete.

  For example, to delete a WebAuthn device, the authentication journey that created the session must also have authenticated using a WebAuthn device.

* Used the [Enable Device Management node](https://docs.pingidentity.com/auth-node-ref/latest/enable-device-management.html) that alters the **Device Check Enforcement Strategy**.

Obtain the device object from `get()`, and then pass it to `delete()`. The `delete()` function returns a `Promise` that resolves with the deleted device object.

* Push devices

* WebAuthn devices

Deleting a Push authenticator device on React Native

```typescript
const devices = await deviceClient.push.get();
const device = devices[0];

await deviceClient.push.delete(device);
console.log('Push device deleted');
```

Deleting a WebAuthn device on React Native

```typescript
const devices = await deviceClient.webAuthn.get();
const device = devices[0];

await deviceClient.webAuthn.delete(device);
console.log('WebAuthn device deleted');
```

## Handling errors

All device client operations throw a `DeviceClientError` when they fail.

`DeviceClientError` extends the base `PingError` class and exposes a `code` property you can use to identify the cause and take appropriate action, such as redirecting to login when a token expires.

The following code shows how to handle errors from a device operation:

Handling errors on React Native

```typescript
import { DeviceClientError } from '@ping-identity/rn-device-client';

try {
  const devices = await deviceClient.oath.get();
} catch (error) {
  if (error instanceof DeviceClientError) {
    switch (error.code) {
      case 'DEVICE_CLIENT_INVALID_TOKEN':
        // SSO token is missing, expired, or rejected — re-authenticate
        break;
      case 'DEVICE_CLIENT_NETWORK_ERROR':
        // Network connectivity failure
        break;
      case 'DEVICE_CLIENT_NOT_FOUND':
        // The requested device does not exist on the server
        break;
      default:
        console.error('Device operation failed:', error.message);
    }
  }
}
```

The module returns the following error codes:

| Error code                       | Description                                                                                                                   |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `DEVICE_CLIENT_ERROR`            | Generic or unknown error.                                                                                                     |
| `DEVICE_CLIENT_NETWORK_ERROR`    | Network connectivity failure.                                                                                                 |
| `DEVICE_CLIENT_REQUEST_FAILED`   | The server returned a non-success HTTP status.                                                                                |
| `DEVICE_CLIENT_INVALID_TOKEN`    | The SSO token is missing, expired, or rejected by the server.Obtain a fresh token by triggering a new authentication journey. |
| `DEVICE_CLIENT_DECODING_FAILED`  | The native bridge could not parse the server response.                                                                        |
| `DEVICE_CLIENT_MISSING_CONFIG`   | Required configuration fields were not provided to `createDeviceClient()`.                                                    |
| `DEVICE_CLIENT_NOT_FOUND`        | The requested device does not exist on the server.                                                                            |
| `DEVICE_CLIENT_HANDLE_NOT_FOUND` | The client has already been disposed.Call `createDeviceClient()` again to obtain a new client instance.                       |
