# Develop with Orchestration SDK: React Native

This guide describes how to quickly integrate Journeys into your React Native application.

## Introduction

The Orchestration React Native SDK enables client-side developers to build user experiences that interact with journeys.

Each journey contains a business workflow, such as login or secure user onboarding. It consists of backend steps, such as data processing or invoking external systems, and client-facing steps, such as a login form or identity verification. The SDK allows the client application to present screens and prompt for user input, and then send this information back to the journey for further processing.

Whenever the client-side interaction requires additional Mosaic platform capabilities, such as passkeys or risk detection, the developer needs to activate the appropriate SDK module to perform the step and collect the required input. This allows separation of concerns between the journey workflow handling, and the specific capability used.

## SDK lifecycle

Regardless of journey logic, the SDK lifecycle consists of the following:

div
𝟷
. 
 Perform a one-time 
a
initialization
 before module first use.
br
𝟸
. 
 Activate 
code
startJourney()
 and wait for the server response
br
𝟹
. 
 Check 
code
TSIDOModule.ServiceResponse
 and present the appropriate UX. If needed, operate additional Mosaic SDKs.
br
𝟺
. 
 Return client input via 
code
submitClientResponse()
 (allows selecting a journey branch if supported by journey step)
br
𝟻
. 
 Repeat 3 and 4 until receiving 
code
success
 or 
code
rejection
The above is reflected in the following workflow diagram:


```mermaid
sequenceDiagram
  participant user as User
  participant app as Client Application
  participant sdk as Orchestration SDK
  participant server as Mosaic

  user ->> app: click login
  opt If not initialized
  app ->> sdk: initialize()
  end
  app ->> sdk: startJourney(journey-id, optional parameters)
  sdk ->> server: forward start-journey parameters
  server ->> server: process server-side<br>journey steps
  server -->> sdk: journey service response
  sdk -->> app: idoServiceResponse object<br>describes required client step<br>or journey completion
  loop while the response is not "success" or "rejection"
  app ->> app: present UI per idoServiceResponse.journeyStepId<br>use additional SDK modules if needed (eg passkey)
  user ->> app: interact as needed
  app ->> sdk: submitClientResponse(selected-option, data)<br>selected-option affects journey branch<br>if multiple options are available
  sdk ->> server: forward client response
  server ->> server: process incoming data<br>and further steps
  server ->> sdk: journey service response
  sdk -->> app: idoServiceResponse object<br>describes required client step<br>or journey completion
  end
  app ->> app: post journey UX, if completed
```

## Before you start

Before the SDK can start running journeys, make sure to:
☐   Coordinate with the journey developer (regarding journey ID, steps, expected data, etc).
☐    Obtain the Client ID that identifies the app, from the app settings in the Admin Portal
☐    Allow Mosaic IPs and [domains](/guides/quick_start/enable_communication) on your network

## Step 1: Installation

### 1. Install React Native module

Install the Mosaic React Native orchestration module in your project folder.

npm

```shell
npm install react-native-ts-identity-orchestration
```

yarn

```shell
yarn add react-native-ts-identity-orchestration
```

### 2. Install iOS native dependencies

The react module requires the Mosaic iOS SDK to be installed using Cocoa Pods in your project's iOS folder.


```shell
cd YOUR_PROJECT_PATH/ios
pod install
```

Note
As part of the project setup, you might need to set permissions, based on the specific module being used.

For example, to collect Face ID permissions, provide an explanation for using them. Open the Info.plist file as a **Property List and add Privacy - Face ID Usage Description** key and provide a reason, such as "This app uses Face ID to provide secure authentication"

### 3. Install Android native dependencies

Add the following lines in the shared build.gradle file ("allprojects" scope):


```groovy
dependencyResolutionManagement {
    repositories {
        maven {
            url('https://transmit.jfrog.io/artifactory/transmit-security-gradle-release-local/')
        }
        mavenCentral()
        google()
    }
}
```

details
summary
b
Try to compile your app in Android Studio
If you get a compile error:
`Manifest merger failed : Attribute application@allowBackup value=(false)`

1. Open your `AndroidManifest.xml` file
2. Add `xmlns:tools="http://schemas.android.com/tools"` to the main manifest tag
3. Add `tools:replace="android:allowBackup"` to the top of the `application` tag.


## Step 2: Initialize the SDK

Initializing the SDK configures it to work with your client ID, which is the context under which the entire journey is executed. It also allows setting the base URL for the SDK to use, whether a Mosaic-provided path or your own proxy.

### 1. iOS initialization configuration

1. Open your project's `.xcworkspace` found under `YOUR_PROJECT_PATH/iOS` in Xcode.
2. Create a plist file named `TransmitSecurity.plist` in your Application with the following content. CLIENT_ID is configured in your Mosaic server. Make sure to add the file to your iOS project.


Here's an example of the plist file:


```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>credentials</key>
    <dict>
      <key>baseUrl</key>
      <string>[BASE_URL]</string> <!--Default is https://api.transmitsecurity.io-->
      <key>clientId</key>
      <string>[CLIENT_ID]</string>
    </dict>
  </dict>
</plist>
```

### 2. Android initialization configuration

1. Open your Android manifest XML file, usually located at `android/app/src/main`.
2. Update the strings.xml file in your Application with the following content. The CLIENT_ID should be replaced with your client ID.



```xml
<resources>
    <!-- Mosaic Credentials -->
    <string name="transmit_security_client_id" translatable="false">[CLIENT_ID]</string >
    <string name="transmit_security_base_url">[BASE_URL]</string>  <!-- Default is https://api.transmitsecurity.io-->
</resources>
```

Note
If you're using a [custom domain](/guides/deployment/custom_domains) for your application, set `baseUrl` (iOS) or `transmit_security_base_url` (Android) to your custom domain instead of the default Transmit domain.

The Android SDK is required to be initialized in your App's Main Application class. To do that, open your MainApplication.kt file and add the following to the bottom of the function `onCreate()`:


```kotlin
TsIdentityOrchestrationModule.initializeAndroidSDK(this)
```

### 3. Initialize React module


```javascript
import RNTSIdentityOrchestration, { TSIDOModule } from 'react-native-ts-identity-orchestration';

/**
  Creates a new Orchestration SDK instance with your client context.
  Credentials are configured from TransmitSecurity.plist file (iOS) or manifest file (Android).
*/
try {
    if (Platform.OS === 'ios') {
      this.idoSDK.initializeSDK();
    } else {
      // Initialize Android SDK on MainApplication.kt (see details above)
    }
} catch (error) {
    console.error('Error initializing IDO service', error);
}
```

## Step 3: Start journey

Starting a journey is usually a response to some user interaction, such as clicking a login or sign-up button.  The start parameters indicate which journey to start, and optionally pass additional parameters if the journey expects them.

For example, if the client app uses email as the user identifier and caches it locally after sign-up, it can pass it to the journey as `userEmail`. The journey can reference it using this expression `@policy.request().params.userEmail`


```javascript
import RNTSIdentityOrchestration, { TSIDOModule } from 'react-native-ts-identity-orchestration';

export type ServiceSuccessCallback = (results: TSIDOModule.ServiceResponse) => void;
export type ServiceErrorCallback = (results: TSIDOModule.JourneyErrorType) => void;

/**
     Sample function that starts a Journey with a given id.
     Sets handlers for success or failure responses for the startJourney() call and future
     submitClientResponse() calls.
    - Parameters:
      - journeyId: Journey Identifier in the Mosaic Admin Console.
      - additionalParams: Additional parameters to be passed to the journey.
      - Success and Error blocks to process responses
*/
public startJourneyWithId = (
    journeyId: string,
    additionalParams: { [key: string]: any; } | null,
    onSuccess: ServiceSuccessCallback,
    onError: ServiceErrorCallback
) => {

    const idoSDK = RNTSIdentityOrchestration;
    let options: TSIDOModule.StartJourneyOptions | null = null;
    if (additionalParams) {
        options = {
            flowId: 'some_optional_flow_id'
            additionalParams: additionalParams
        };
    }

    idoSDK.setResponseHandler({
        success: (results: TSIDOModule.ServiceResponse) => {
            onSuccess(results);
        },
        error: (error: TSIDOModule.JourneyErrorType) => {
            onError(error);
        }
    });

    idoSDK.startJourney(journeyId, options);
  }

startJourneyWithId('my_journey_id', {
  userEmail: 'name@example.com'
})
```

## Step 4: Handle service response

After successfully starting the journey, the client app success handler receives the `TSIDOModule.ServiceResponse`. It will contains all the information the client needs in order to determine what to do next.

To handle the service response, the client app needs to:

1. [Select a handler based on the step](#1-select-handler)
2. [Use the data provided by the journey](#2-use-data-sent-from-journey)
3. [Respond to the journey with requested input](#3-respond-with-collected-data)


### 1. Select handler

Upon receiving the `TSIDOModule.ServiceResponse`, the success handler acts on the relevant step by switching/selecting on the `TSIDOModule.ServiceResponse.journeyStepId` parameter. It will either contain one of these [enums](https://transmitsecurity.github.io/identityOrchestration-ios-sdk-docs/documentation/identityorchestration/tsidojourneyactiontype) or `'custom-step-id'` where *custom-step-id* is the unique **Step ID** configured in the [Login Form](/guides/orchestration/journeys/login_form) or [Collect information](/guides/orchestration/journeys/get_info_from_client) steps. Each handler should process the data, display whatever UI is needed, and call `submitClientResponse()` when the interaction is concluded.

This is how the success handler code would dispatch handlers based on this property:


```javascript
private handleJourneyServiceResponse = (results: TSIDOModule.ServiceResponse) => {
    switch (results.journeyStepId) {
        // Prefixed Steps
        case TSIDOModule.JourneyActionType.success: this.props.onJourneyEndedWithSuccess(results); break;
        case TSIDOModule.JourneyActionType.rejection: this.props.onJourneyEndedWithRejection(results); break;
        case TSIDOModule.JourneyActionType.information: console.log('information'); break;
        case TSIDOModule.JourneyActionType.debugBreak: console.log("debugBreak"); break;
        case TSIDOModule.JourneyActionType.waitForAnotherDevice: console.log("waitForAnotherDevice"); break;
        case TSIDOModule.JourneyActionType.drsTriggerAction: console.log("drsTriggerAction"); break;
        case TSIDOModule.JourneyActionType.identityVerification: console.log("identityVerification"); break;
        case TSIDOModule.JourneyActionType.webAuthnRegistration: console.log("webAuthnRegistration"); break;
        case TSIDOModule.JourneyActionType.registerDeviceAction: console.log("registerDeviceAction"); break;
        case TSIDOModule.JourneyActionType.validateDeviceAction: console.log("validateDeviceAction"); break;
        case TSIDOModule.JourneyActionType.nativeBiometricsRegistration: console.log("nativeBiometricsRegistration"); break;
        case TSIDOModule.JourneyActionType.nativeBiometricsAuthenticaton: console.log("nativeBiometricsAuthenticaton"); break;
        case TSIDOModule.JourneyActionType.emailOTPAuthentication: console.log(''); break;
        case TSIDOModule.JourneyActionType.smsOTPAuthentication: console.log("smsOTPAuthentication"); break;

        // Custom Steps
        case `userRegistrationForm-custom-step-id`: this.handleUserRegistrationForm(results); break;
        default: logger.warn(`handleJourneyServiceResponse: Unknown journey step: ${results.journeyStepId}`); break;
    }
}
```

Note
Make sure to add import statement at the top of the code file:
`import RNTSIdentityOrchestration, { TSIDOModule } from 'react-native-ts-identity-orchestration';`

### 2. Use data sent from journey

Inside the handler function, the app code should render a UI that fits the specific step, and use information from the `data` property if it was provided in the `TSIDOModule.ServiceResponse` object. This data is described in each [step guide](/guides/journeys_intro).

Let's see an example for a [Display Information](/guides/orchestration/journeys/display_information) step. `TSIDOModule.ServiceResponse` will include `journeyStepId` set to `.information` and a `data` object containing text to present as configured by the journey author. This text can be presented as shown below:


```javascript
interface MyAuthenticationContainerProps {
    route: RouteProp<any, any>;
    navigation: StackNavigationProp<any, any>;
}

interface MyAuthenticationContainerState {
    presentingView: React.ReactNode | null;
}

class MyAuthenticationContainer extends React.Component<MyAuthenticationContainerProps, MyAuthenticationContainer> {

  // Information Step (JourneyActionType) handler
  private handleInformationStep = async (idoServiceResponse: TSIDOModule.ServiceResponse) => {
      logger.log(`Handle Information Step: ${JSON.stringify(idoServiceResponse)}`);

      const data = idoServiceResponse.data;
      if (!data) return;

      const handler = () => {
        // Place here the last step, respond with collected data (if any), see next section
      }

      // Render information screen presenting title, text and button text provided by the ServiceResponse
      // Mosaic React Native module does not provide UI components. The application developer should provide
      // their own components.
      const informationView = this.myAppComponentGenerator.informationScreen(
          data.title, data.text, data.button_text, handler
      );

      this.setState({ presentingView: informationView });
  }
}
```

Note
Make sure to add import statement at the top of the code file:
`import RNTSIdentityOrchestration, { TSIDOModule } from 'react-native-ts-identity-orchestration';`

### 3. Respond with collected data

Once the user interaction is concluded, the handler should collect the response data and submit it using `submitClientResponse()`. This call yields control back to the journey, and returns with a new `TSIDOModule.ServiceResponse` once the journey reaches the next client-facing step.

The new `TSIDOModule.ServiceResponse` is handled the same way the service response was handled when returned from `startJourney()` call. See `setResponseHandler` invocation in the sample code in [Start journey](#step-3-start-journey).

The call parameters are the collected data, and a response option identifier. We’ll talk more about these below. For now, let's follow the [Display Information](/guides/orchestration/journeys/display_information) example of making this call.


```javascript
// Example for responding to Information step
this.idoSDK.submitClientResponse(TSIDOModule.ClientResponseOptionType.clientInput);
```

In this simple example, the journey was pending a signal from the client that it may continue to the next journey steps. However, no additional data was required.

In many other client-facing journey steps, data such as a password or user information may be collected from the client using the `response_data` object. For example, in Email OTP authentication, after receiving the email, the user is required to provide the OTP code. The response call may look like this:


```javascript
// Example for responding to Email OTP step
const onSubmitPressed = (otp_code) => {
  let response_data = { passcode: otp_code };
  idoSDK.submitClientResponse(TSIDOModule.ClientResponseOptionType.clientInput, response_data);
}
```

details
summary
b
About response data schema
Each journey step expects specific fields to be sent back in the data object. The details of the expected fields are described in the relevant [step guide](/guides/journeys_intro). As seen above, when we use the example of the [Register Passkeys](/guides/orchestration/journeys/register_webauthn) step, the expected data is a field called `webauthn_encoded_result` which is the output of the Passkey registration SDK.

For most journey steps, the client response schema is fixed. However, there are two steps that expect a dynamic schema. The [Login Form](/guides/orchestration/journeys/login_form) step allows presenting multiple authentication options and collects input for one of them. The [Collect information](/guides/orchestration/journeys/get_info_from_client) step allows presenting an arbitrary data collection form to the end user. For both steps, the expected data schema is configured in the step. The client developer must coordinate with the journey author for the expected schema for each Step ID.

details
summary
b
About alternate branches and response options
Certain steps support multiple response options. These options are passed in the `TSIDOModule.ServiceResponse` object in the `clientResponseOptions` property. These represents possible replies that the client can provide as a response to a journey step, and affect the branch that is taken when the step is completed.

Three of these replies have a standard type (per SDK):

- `clientInput` represents a typical reply to a step that has a main or single output path. See above the example for [Register Passkeys](/guides/orchestration/journeys/register_webauthn) is using this reply option. This would be the common reply option to most steps.
- `cancel` chooses the cancel branch in actions that support it
- `fail` chooses the failure branch in actions that support it


Apart from those, some journey steps support alternate (custom) branches. The **Branch ID** is configured by the journey author, and should be used to identify the branch when calling `submitClientResponse()`. The example below submits a response to the [Login Form](/guides/orchestration/journeys/login_form) step, where one of the alternate branches proceed to passkey authentication. This branch also expects a specific schema (that can be customized by the journey author) - the default is getting the encoded result after activating the authentication SDK.


```javascript
let data = { webauthn_encoded_result: "<encodedAuthenticationResult>" }
idoSDK.submitClientResponse(
    clientResponseOptionId: "passkey",
    data: data
});
```

## Step 5: Complete journey

Mosaic signals journey completion by setting the `journeyStepId` property to `rejection` or `success`. The specific enum for each SDK is described in  [Select handler](#1-select-handler) above. If successful, the `token` property contains a token as a proof of journey completion.

## Next steps

The SDK also supports the features below. For more info, talk to your Transmit Security representative.

- Generating a debug pin for the journey debugger
- Local console logs
- Resources URIs as part of SDK initialization


style

    section article ol li {
      margin-top: 6px !important;
    }
    .lifecycleSteps {
      line-height: 30px !important;
    }