# Incode Onboarding Cordova Plugin

**Incode Onboarding** provides effortless onboarding where security matters.  
It is a part of Incode Omnichannel Biometric Identity Platform, that is powered by Incode's world class Face Recognition, Liveness detection and ID Validation models. Organizations can choose to have an optional video conference to additionally verify the customer’s identity.

In this repo you can find an example onboarding app that uses Incode Onboarding Cordova Plugin to enable remote account opening.

## Supported Android Version

API 21+ & CompileSDK version 35.

Android builds require Java 11 or newer.

## Supported iOS Version

iOS 13+

## Installation

Install the **Incode Onboarding Cordova Plugin** in your app path using command:

```shell
cordova plugin add incode-cordova-plugin
```

OR

```shell
cordova plugin add https://github.com/Incode-Technologies-Example-Repos/CordovaPluginReleases.git
```

OR for `nfc` version of the plugin

```shell
cordova plugin add "https://github.com/Incode-Technologies-Example-Repos/CordovaPluginReleases.git#release/[VERSION]-nfc"
```

As our SDK needs camera to capture ID and face, use command:

```shell
 cordova plugin add cordova-plugin-camera
```

Same applies for GeoLocation if its required, use command:

```shell
cordova plugin add cordova-plugin-geolocation
```

### Additional Steps for Android

#### For Cordova

Cordova sample app needs to provide a source from where to fetch Android SDK dependency from.  
Suggested method would be to add a hook within the `config.xml` file that will be triggered after platform is added:

```xml
</platform>  
    <hook type="after_platform_add" src="hooks/after_platform_add/add-incode-maven-repo.js" />  
</widget>
```

`add-incode-maven-repo.js` content that can be reused:

```javascript
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

const repoBlock = `maven {
    url = uri("https://maven.pkg.github.com/Incode-Technologies-Example-Repos/android-omni-packages")
     credentials {
        username = project.findProperty("github_username") ?: System.getenv("GITHUB_USERNAME")
        password = project.findProperty("github_token") ?: System.getenv("GITHUB_TOKEN")
    }
}`;

function removeIncodeMavenBlocks(block) {
    let idx = 0;
    while (true) {
        const mavenIndex = block.indexOf('maven {', idx);
        if (mavenIndex === -1) break;
        // Only consider blocks containing the Incode repo URL
        const urlIdx = block.indexOf('repo.incode.com/artifactory/libs-incode-welcome', mavenIndex);
        if (urlIdx === -1) {
            idx = mavenIndex + 7;
            continue;
        }
        // Find the matching closing brace for maven { ... }
        let braceCount = 0;
        let endIdx = mavenIndex;
        let found = false;
        for (; endIdx < block.length; endIdx++) {
            if (block[endIdx] === '{') braceCount++;
            else if (block[endIdx] === '}') braceCount--;
            if (braceCount === 0 && endIdx > mavenIndex) {
                found = true;
                break;
            }
        }
        if (found) {
            block = block.slice(0, mavenIndex) + block.slice(endIdx + 1);
            idx = mavenIndex; // Continue searching after removed block
        } else {
            break; // Malformed, stop
        }
    }
    return block;
}

function insertRepoFirst(block) {
    block = removeIncodeMavenBlocks(block);
    return block.replace(/repositories\s*\{/, match => `${match}\n${repoBlock}\n`);
}

function patchGradle(context) {
    const projectRoot = context.opts && context.opts.projectRoot ? context.opts.projectRoot : process.cwd();
    const appGradlePath = path.join(projectRoot, 'platforms/android/app/build.gradle');
    if (!fs.existsSync(appGradlePath)) {
        console.log('app/build.gradle not found:', appGradlePath);
        return;
    }
    let appGradle = fs.readFileSync(appGradlePath, 'utf8');

// Patch buildscript
    appGradle = appGradle.replace(/(buildscript\s*\{[\s\S]*?)(\n\s*dependencies\s*\{)/, (match, p1, p2) => {
        let beforeDeps = p1;
        if (/repositories\s*\{/.test(beforeDeps)) {
            beforeDeps = insertRepoFirst(beforeDeps);
        } else {
            beforeDeps = beforeDeps.replace(/buildscript\s*\{/, m => `${m}\n    repositories {\n${repoBlock}\n    }\n`);
        }
        return beforeDeps + p2;
    });

// Patch allprojects
    appGradle = appGradle.replace(/(allprojects\s*\{[\s\S]*?)(\n\s*task |\n\s*ext |\n\s*android |\n\s*\/\*|$)/, (match, p1, p2) => {
        let beforeNext = p1;
        if (/repositories\s*\{/.test(beforeNext)) {
            beforeNext = insertRepoFirst(beforeNext);
        } else {
            beforeNext = beforeNext.replace(/allprojects\s*\{/, m => `${m}\n    repositories {\n${repoBlock}\n    }\n`);
        }
        return beforeNext + p2;
    });

fs.writeFileSync(appGradlePath, appGradle, 'utf8');
}

// Cordova will call as a function during the build, but allow running directly for manual testing
module.exports = patchGradle;
if (require.main === module) {
    patchGradle({ opts: { projectRoot: process.cwd() } });
}
```

#### For Capacitor/Ionic

Modify your project's `build.gradle` so it contains reference to github repository package using `GITHUB_USERNAME` and `GITHUB_TOKEN`, provided by Incode.

```diff
allprojects {
  repositories {
    ...
+    maven {
+    url "https://maven.pkg.github.com/Incode-Technologies-Example-Repos/android-omni-packages"
+      credentials {
+        username = "GITHUB_USERNAME"
+        password = "GITHUB_TOKEN"
+      }
+    }
    ...
  }
}
```

### Additional Steps for iOS

#### For Cordova

Run `pod install` under ios folder.

#### For Capacitor/Ionic

1. Copy below lines into the pod file:

```undefined
source 'https://github.com/CocoaPods/Specs.git'
source 'git@github.com:Incode-Technologies-Example-Repos/IncdDistributionPodspecs.git'
```

2. Run `pod install` or `pod install --repo-update` under `ios/app` folder.
3. Run `npx cap sync`

## Documentation

Following functions can be used to initialize the plugin with different modules as per your business requirement.

### Initialize SDK

Below function will initialize Incode SDK which is required at least once in the app lifecycle.

```javascript
cordova.exec(
    function(param) {
        console.log("Success: "+param);
        // start the incode session here
    },
    function(err) {
        console.log("Error: "+ err);
        // handle the error by showing some UI or alert.
    },
    "Cplugin",
    "initializeSDK",
    [\
        apiKey,\
        apiUrl,\
        loggingEnabled,\
        testMode,\
        isExternalTokenEnabled,\
        disableJailbreakDetection,\
        clientExperimentId,\
        e2eeUrl,\
        {\
            enabled: false,\
            forceSSLPinning: false,\
        }\
    ]);
```

Above function takes the following parameters:

- `apiKey` (string): API key, provided by Incode.
- `apiUrl` (string): API URL, provided by Incode.
- `loggingEnabled` (string): Set to `true` to enable logging, `false` to disable. Default `true`.
- `testMode` (string): Set to `true` if running on simulator/emulators, `false` when running on devices. Default `false`.
- `isExternalTokenEnabled` (string): Set to `true` if using external token authentication, `false` otherwise. Default `false`.
- `disableJailbreakDetection` (string): Set to `true` to disable jailbreak detection. Valid only for iOS. Default `false`.
- `clientExperimentId` (string): Optional client experiment ID used to enroll customer to experimental features like ID V2. Pass `null` or empty string if not used.
- `e2eeUrl` (string): E2EE API URL, provided by Incode. A URL for end-to-end encryption. Supply `null` if not using end-to-end encryption. Default `null`.
- `sslPinningConfig` (object): This is object used to configure SSL pinning. It contains following parameters:

- `enabled` (boolean): Set to true to enable SSL pinning, false otherwise.
  - `forceSSLPinning` (boolean): Set to true to force SSL pinning. Default is `false`

When `sslPinningConfig` is enabled and `forceSSLPinning` is set to true, in case of misconfigured certificate or possible MITM attack SDK will abort the flow and return an error `sslPinningFailed`:

```javascript
cordova.exec(
    function(param) {
        ///
    },
    function(err) {
       if (error === "sslPinningFailed") {
        console.log("SSL pinning failed - possible MITM attack or misconfigured certificate");
       } else {
        console.log("Other error:", error);
       }
     },
   ...
);
```

### Set Common Configuration

Below function will set a common runtime configuration used by both iOS and Android. It should be called after `initializeSDK` but before anything else.

```javascript
cordova.exec(
    function(param) {
        console.log("Success: "+param);
        // common config is set
    },
    function(err) {
        console.log("Error: "+ err);
        // handle the error
    },
    "Cplugin",
    "setCommonConfig",
    [setShowCloseButton]
);
```

It takes the following optional parameter

- `setShowCloseButton` (string): Set to `true` to show a close button. Defaults to `false`.

### Check if SDK is initialized

Below function returns a boolean that resolves to `true` if the native SDK is initialized, otherwise `false`.

```javascript
cordova.exec(
    function(isInitialized) {
        console.log("isInitialized: " + isInitialized);
        // isInitialized is `true` if the SDK is ready, `false` otherwise
    },
    function(err) {
        console.log("Error: "+ err);
        // handle the error
    },
    "Cplugin",
    "isInitialized",
    []
);
```

### Start onboarding

Create a new session based on the specified list of modules.

```javascript
let sessionConfig = {
  configurationId: "your-workflow-id",
};
let flowConfig = [\
  { module: "addPhone" },\
  { module: "addId", showIdTypeChooser: "true", showTutorials: "true" },\
  { module: "addDocumentScan", documentType: "ADDRESS_STATEMENT" },\
  { module: "addGeolocation", "isSkippable": "true" },\
  { module: "addSelfieScan", showTutorials: "true" },\
  { module: "addFaceMatch" },\
  { module: "addSignature" },\
  { module: "addVideoSelfie" }\
];
let recordSessionConfig = {}; // Optional

cordova.exec(
  function (result) {
    console.log("Success startDefaultFlow: ", result);
  },
  function (error) {
    console.log("Error startDefaultFlow:", error);
  },
  "Cplugin",
  "startOnboarding",
  [sessionConfig, flowConfig, recordSessionConfig]
);
```

To change session parameters, specify them inside mandatory `sessionConfig` parameter:
- `region` (string): Specify a region, currently supported are `ALL`(covers all regions), `BR` (optimized for Brazil) and `IN` (optimized for India)
- `queue` (string): Specify a queue to which this onboarding session will be attached to
- `interviewId` (string): In case you're creating an onboarding session on the backend, you can provide its interviewId and the flow will be started for that particular onboarding session
- `configurationId` (string): In case you've created a flow on the dashboard with a specific configuration, you can provide it here so that those settings apply to this session
- `token` (string): In case you're creating an onboarding session on the backend, you can provide its token and the flow will be started for that particular onboarding session
- `externalId` (string): ID used outside of Incode Omni
- `externalCustomerId`(string): This identifier links the onboarding session to an entity in an external system not part of the Incode Omni Platform. It could represent a prospect Id or a customer Id from the client's database, providing a bridge between the Incode session and the client's internal user management systems.
- `validationModules` (json array): List of validation modules that should be enabled in this session
- `customFields` (json object): Custom data that should be attached to this onboarding session
- `e2eEncryptionEnabled` (boolean): Enable e2e encryption.
- `mergeSessionRecordings` (boolean): Indicates whether the session recordings will be compiled into a single video. If set to `true`, the recordings from the ID capture and Face capture will be merged.
- `voiceConsentLanguage` (string): Optionally set the language for voice consent in `VideoSelfie` module. Supported values are currently: 'en', 'es', 'pt' and 'he'.

...

### License

Copyright 2018 Incode Technologies. All rights reserved.  
Updated 25 days ago
