---
title: Integrating FIDO DaVinci flows into React Native apps
description: Integrate FIDO authentication into React Native apps using DaVinci flows, including installing the FIDO module, running passkey ceremonies, and handling errors
component: orchsdks
page_id: orchsdks:davinci:use-cases/fido/react-native/react-native-fido-davinci-flows
canonical_url: https://developer.pingidentity.com/orchsdks/davinci/use-cases/fido/react-native/react-native-fido-davinci-flows.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: Thu, 25 Sep 2026 00:00:00 +0000
keywords: ["FIDO", "WebAuthn", "MFA", "Hardware", "Source Code", "Integration", "SDK", "React Native"]
section_ids:
  rn_fido_module: Step 1. Installing modules
  installing_native_dependencies_on_ios: Installing native dependencies on iOS
  adding_optional_dependencies_on_android: Adding optional dependencies on Android
  step_2_creating_the_fido_client: Step 2. Creating the FIDO client
  step_3_handling_fido2_collectors_in_a_davinci_flow: Step 3. Handling FIDO2 collectors in a DaVinci flow
  configuring_usedavinciform_to_handle_fido_collectors: Configuring useDaVinciForm to handle FIDO collectors
  step_4_registering_fido_authenticators: Step 4. Registering FIDO authenticators
  step_5_authenticating_using_a_fido_authenticator: Step 5. Authenticating using a FIDO authenticator
  step_6_handling_cancellation_and_errors: Step 6. Handling cancellation and errors
  error-codes: Error codes
---

# Integrating FIDO DaVinci flows into React Native apps

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

The FIDO module provides native-backed FIDO capabilities for React Native apps, including registering and authenticating with passkeys.

|   |                                                                                                                                                                  |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Before you beginEnsure you have [prepared PingOne for FIDO authentication in React Native apps](before-you-begin.html) before completing the steps on this page. |

## Step 1. Installing modules

The FIDO module for React Native is available as the `@ping-identity/rn-fido` npm package.

The module requires the `@ping-identity/rn-core` package. Install both packages in your React Native project:

* yarn

* npm

```shell
yarn add @ping-identity/rn-core @ping-identity/rn-fido
```

```shell
npm install @ping-identity/rn-core @ping-identity/rn-fido
```

### Installing native dependencies on iOS

After installing the package, install the native iOS dependencies using CocoaPods:

```shell
cd ios && pod install
```

### Adding optional dependencies on Android

Gradle resolves the Android native dependencies automatically.

Optionally, add the following dependencies to your app's `build.gradle` if needed:

* If your app targets Android API 33 (Android 13) or older, add `androidx.credentials:credentials-play-services-auth` to ensure FIDO functions correctly on those devices.

* If your app needs to support non-discoverable FIDO credentials or physical security keys, add `com.google.android.gms:play-services-fido`.

## Step 2. Creating the FIDO client

Create a FIDO client by calling `createFidoClient()`.

Create the client once and reuse it for the lifetime of the relevant screen or session, for example with a `useMemo` hook:

Creating the FIDO client

```typescript
import { createFidoClient } from '@ping-identity/rn-fido';

const fidoClient = createFidoClient();
```

You can call `createFidoClient()` without arguments.

The client does not require configuration for the DaVinci ceremony methods, `registerForDaVinci()` and `authenticateForDaVinci()`. These methods build their own native FIDO client and use the logger configured in the DaVinci workflow, so client-level options such as `logger` have no effect on them.

## Step 3. Handling FIDO2 collectors in a DaVinci flow

When a DaVinci flow reaches a FIDO step, the flow returns a `ContinueNode` containing a FIDO2 collector.

DaVinci flows represent each FIDO operation as a single `FIDO2` collector, and the collector's `action` property tells you which operation it performs:

* `REGISTER`

  A registration collector. The user is registering a new passkey with the flow.

* `AUTHENTICATE`

  An authentication collector. The user is authenticating with an existing passkey.

To support this flow, your app needs to:

* Create the form with the node from `useDaVinci`, and pass `FIDO2` in `handledCollectorTypes`.

* Render a passkey button for each FIDO2 collector in the node.

* Call `registerForDaVinci` or `authenticateForDaVinci` depending on the collector's `action`, then advance the flow with `daVinci.next({ collectors: [] })`.

### Configuring `useDaVinciForm` to handle FIDO collectors

The `useDaVinciForm` hook manages form state for the collectors on the active DaVinci node, and plans what the app submits when the form is complete.

Create the form with the node from `useDaVinci`, and pass the `FIDO2` collector type in `handledCollectorTypes` so the FIDO collectors are excluded from blocking submit issues:

Configuring useDaVinciForm to handle FIDO collectors

```typescript
import { useDaVinci, useDaVinciForm } from '@ping-identity/rn-davinci';
import { fidoCollectorType } from '@ping-identity/rn-fido';

const { node, next } = useDaVinci(daVinciClient);

const form = useDaVinciForm(node, {
  handledCollectorTypes: new Set([fidoCollectorType]),
});
```

Without `handledCollectorTypes`, each `FIDO2` collector raises an `INTEGRATION_REQUIRED` issue and forces `form.canSubmit` to `false`, because the module treats these collectors as requiring client-side integration.

When you list `FIDO2` in `handledCollectorTypes`, your app declares that it handles these collectors itself, and `form.canSubmit` reflects the readiness of the remaining form fields.

> **Collapse: What fields are available in a FIDO2 collector?**
>
> The FIDO collector exposes the following fields:
>
> | Field                                | Type                             | Description                                                                                                        |
> | ------------------------------------ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
> | `key`                                | `string`                         | Stable server-assigned identifier used as the collector key.                                                       |
> | `type`                               | `'FIDO2'`                        | The collector type.Always `FIDO2` for FIDO collectors.                                                             |
> | `action`                             | `'REGISTER'` or `'AUTHENTICATE'` | The ceremony action.Use this value to decide whether to call `registerForDaVinci()` or `authenticateForDaVinci()`. |
> | `label`                              | `string`                         | Human-readable label rendered for the collector.                                                                   |
> | `required`                           | `boolean`                        | Whether the collector must be completed before submission.                                                         |
> | `trigger`                            | `string`, optional               | Android-only trigger string surfaced by the native collector.The iOS collector does not expose this field.         |
> | `publicKeyCredentialCreationOptions` | `object`, optional               | WebAuthn public key credential creation options returned by the server, on registration collectors.                |
> | `publicKeyCredentialRequestOptions`  | `object`, optional               | WebAuthn public key credential request options returned by the server, on authentication collectors.               |
> | `raw`                                | `object`, optional               | Original server-side field JSON when available.                                                                    |

## Step 4. Registering FIDO authenticators

To register a FIDO authenticator, call `registerForDaVinci()` on the FIDO client with the active DaVinci client.

The method runs the native platform passkey ceremony, and the native layer submits the resulting attestation to the flow before the method returns:

Registering a FIDO authenticator in a DaVinci flow

```typescript
async function handleFidoCeremony(collector) {
  if (collector.action === 'REGISTER') {
    await fidoClient.registerForDaVinci(daVinciClient, { index });
    await next({ collectors: [] });
  }
}
```

The `daVinciClient` parameter is a DaVinci client created with `createDaVinciClient()`. Learn more in [Configuring the DaVinci module in React Native](../../../usage/react-native/03-configuring-the-davinci-module.html).

If the node contains more than one `FIDO2` registration collector, pass the zero-based `index` of the collector the user chose.

|   |                                                                                                                                                                                                                          |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|   | The attestation payload returned by `registerForDaVinci` is informational only.The native layer submits the credential to the DaVinci flow itself, which is why the call to `next()` passes an empty `collectors` array. |

## Step 5. Authenticating using a FIDO authenticator

To authenticate using a registered FIDO authenticator, call `authenticateForDaVinci()` on the FIDO client.

The method runs the native platform passkey ceremony, and the native layer submits the resulting assertion to the flow before the method returns:

Authenticating with a FIDO authenticator in a DaVinci flow

```typescript
async function handleFidoCeremony(collector) {
  if (collector.action === 'AUTHENTICATE') {
    await fidoClient.authenticateForDaVinci(daVinciClient, { index });
    await next({ collectors: [] });
  }
}
```

If the node contains more than one `FIDO2` authentication collector, pass the zero-based `index` of the collector the user chose.

Because both ceremony methods submit their result through the native layer, a common pattern is to branch on the collector's `action` in a single handler and advance the flow after the ceremony resolves:

Handling both FIDO actions in one handler

```typescript
import type { FidoCollector } from '@ping-identity/rn-fido';

async function handleFidoCeremony(collector: FidoCollector): Promise<void> {
  const fidoFields = form.fields.filter(
    (f) => f.type === fidoCollectorType &&
      (f as FidoCollector).action === collector.action,
  );
  const index = fidoFields.findIndex((f) => f.key === collector.key);

  try {
    if (collector.action === 'REGISTER') {
      await fidoClient.registerForDaVinci(daVinciClient, { index });
    } else {
      await fidoClient.authenticateForDaVinci(daVinciClient, { index });
    }
    await next({ collectors: [] });
  } catch (err) {
    // Handle the error, see below
  }
}
```

|   |                                                                                                                                                                                                                                                       |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | When a node contains both registration and authentication collectors, compute the `index` within the subset of collectors matching the ceremony action, because the native resolvers index collectors separately for registration and authentication. |

## Step 6. Handling cancellation and errors

When a FIDO operation fails or is cancelled, the SDK throws a `FidoError`.

Use the `code` property to distinguish cancellation from other failures:

Handling FIDO cancellation and errors

```typescript
import { FidoError } from '@ping-identity/rn-fido';

try {
  await handleFidoCeremony(collector);
} catch (err) {
  if (err instanceof FidoError) {
    if (err.code === 'FIDO_AUTHENTICATE_CANCELLED') {
      // Non-fatal. On Android this also fires when the device has no
      // enrolled passkey (NoCredentialException), in which case routing
      // the user to registration may be more appropriate than offering
      // a fallback authentication path.
      return;
    }
    // For other errors, fall through and advance the flow
    // so the server can route to its configured failure branch
  }
  await next({ collectors: [] });
}
```

### Error codes

| Error code                    | Description                                                                                                                                                                                                                                                                                                                                                                                 |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `FIDO_ERROR`                  | A general FIDO error that does not fall into a more specific category.                                                                                                                                                                                                                                                                                                                      |
| `FIDO_REGISTER_ERROR`         | Registration failed. The platform reported an error creating the credential.                                                                                                                                                                                                                                                                                                                |
| `FIDO_AUTHENTICATE_ERROR`     | Authentication failed due to a platform or server-side error.                                                                                                                                                                                                                                                                                                                               |
| `FIDO_AUTHENTICATE_CANCELLED` | The FIDO authentication ceremony ended without an assertion. This can be caused by any of the following:- The user dismissed the prompt

- The device has no eligible passkey (Android)

- The platform reported a generic authorization failure.

  &#xA;&#xA;iOS reports failures and cancellations identically.You can treat this as non-fatal and offer a fallback authentication path. |
| `FIDO_ACTIVITY_UNAVAILABLE`   | The Android Activity required to launch the FIDO UI is unavailable.                                                                                                                                                                                                                                                                                                                         |
| `FIDO_WINDOW_UNAVAILABLE`     | The iOS window required to present the FIDO UI is unavailable.                                                                                                                                                                                                                                                                                                                              |
| `FIDO_COLLECTOR_NOT_FOUND`    | The module could not find a matching `FIDO2` collector in the DaVinci node.                                                                                                                                                                                                                                                                                                                 |
