A foundation package that provides a native-backed bridge for managing a user's registered MFA and profile devices (OATH, Push, Bound, WebAuthn, Profile) from React Native.
Note: This module requires that the
@ping-identity/rn-coremodule is already set up and installed.
# Install & setup the core module
yarn add @ping-identity/rn-core
# Install the rn-device-client module
yarn add @ping-identity/rn-device-client
# If you are developing your app using iOS, run this command
cd ios && pod install
Optional integration packages:
yarn add @ping-identity/rn-logger
You need a valid SSO token from an authenticated user. In Journey apps the
token is available via ssoToken() on the Journey hook actions.
The following config values are required — there are no defaults:
| Field | Example | Source |
|---|---|---|
serverUrl |
'https://openam.example.com/am' |
Server base URL |
ssoToken |
session.value |
Journey SSO token |
realm |
'alpha' |
Authentication realm |
cookieName |
'5421aeddf91aa20' |
Session cookie header |
createDeviceClient is the imperative API for managing devices. It is a
foundation-level export — no dependency on Journey, OIDC, or any provider.
import { createDeviceClient } from '@ping-identity/rn-device-client';
const client = createDeviceClient({
serverUrl: 'https://openam.example.com/am',
ssoToken: session.value,
realm: 'alpha',
cookieName: '5421aeddf91aa20',
});
const oathDevices = await client.oath.get();
await client.bound.update({ ...boundDevice, deviceName: 'My iPhone' });
await client.webAuthn.delete(webAuthnDevice);
// Optional: release native resources when you no longer need the client.
// For app-scoped clients you can skip this — the OS reclaims everything
// when the process exits.
await client.dispose();
The returned DeviceClient exposes five repositories matching the native
SDKs 1:1: oath, push, bound, profile, webAuthn. Each repository
has get(), update(device), and delete(device).
import { logger } from '@ping-identity/rn-logger';
const client = createDeviceClient({
serverUrl: 'https://openam.example.com/am',
ssoToken: session.value,
realm: 'alpha',
cookieName: '5421aeddf91aa20',
logger: logger({ level: 'debug' }),
});
No hook ships with this package — createDeviceClient is imperative by
design so the foundation stays React-agnostic. For a reference React
hook that wires Journey's SSO token into createDeviceClient, see
PingSampleApp/src/hooks/useDevices.ts.
| Kind | JS key | Description |
|---|---|---|
| OATH | oath |
TOTP/HOTP authenticator apps. |
| Push | push |
Push-notification devices. |
| Bound | bound |
Device-binding (cryptographic) MFA. |
| WebAuthn | webAuthn |
FIDO2 / WebAuthn credentials. |
| Profile | profile |
Tracked device profiles (metadata / location). |
All timestamps (createdDate, lastAccessDate, lastSelectedDate) are
normalized to milliseconds since epoch so you can pass them directly
to new Date(...).
import { createDeviceClient } from '@ping-identity/rn-device-client';
import type {
DeviceClient,
DeviceClientConfig,
DeviceKind,
OathDevice,
PushDevice,
BoundDevice,
WebAuthnDevice,
ProfileDevice,
DeviceLocation,
DeviceClientError,
DeviceClientErrorCode,
} from '@ping-identity/rn-device-client';
function createDeviceClient(config: DeviceClientConfig): DeviceClient;
DeviceClient:
interface DeviceClient {
oath: DeviceRepository<OathDevice>;
push: DeviceRepository<PushDevice>;
bound: DeviceRepository<BoundDevice>;
profile: DeviceRepository<ProfileDevice>;
webAuthn: DeviceRepository<WebAuthnDevice>;
dispose(): Promise<void>;
}
interface DeviceRepository<T> {
get(): Promise<T[]>;
update(device: T): Promise<T>;
delete(device: T): Promise<T>;
}
Rejected promises throw a DeviceClientError instance, which extends PingError extends Error. Use instanceof DeviceClientError to narrow in catch blocks.
Stable error codes:
DEVICE_CLIENT_ERRORDEVICE_CLIENT_NETWORK_ERRORDEVICE_CLIENT_REQUEST_FAILED (includes status)DEVICE_CLIENT_INVALID_TOKENDEVICE_CLIENT_DECODING_FAILEDDEVICE_CLIENT_MISSING_CONFIGDEVICE_CLIENT_NOT_FOUNDDEVICE_CLIENT_HANDLE_NOT_FOUNDMIT