iOS SDK Integration (Beta)

SDK Errors

Our iOS DI SDK reports errors using a numeric code and a message. These errors are the following:

  • 20001: "API Key is missing"
  • 20002: "Process canceled"
  • 20003: "Identity process has no next actions"
  • 20004: "Action is invalid"
  • 20005: "Identity process is invalid"
  • 20006: "Validation declined"
  • 20007: "Validation expired"
  • 20008: "Validation failed due to system error"
  • 20009: "Validation failed"
  • 20010: "Process cancelled by the user"
  • 20011: "Camera permission denied, process cannot continue"
  • 20012: "File upload link is invalid"
  • 20013: "Process was interrupted. Please try again"
  • 20014: “Missing module.”
  • 20015: “This flow is not available at the moment”
  • 20500: "Unexpected error"
  • 30001: "File could not be uploaded. Please try again"
  • 30002: "Face not detected in document. Please try again"
  • 30003: "The temporary api key has expired. Please try again"
  • 40001: “Network request failed.”
  • 40002: “Invalid status code {{code}} during response {{httpResponse}}.”
  • 40003: “Invalid format during response {{httpResponse}}”
  • 40004: “Session disconnected”

Getting started

Add the SDK dependencies

Cocoa Pods In your Podfile add the necessaries pods from the DI SDK to start the project, for example:

target '<target>' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  pod 'Truora/TruoraCore', ‘<version>’
  pod 'Truora/TruoraDocument, ‘<version>’
end

# Only include this post install hook if these dependencies are used on your app
truora_dependencies = ['Alamofire']

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if truora_dependencies.include? target.name
      target.build_configurations.each do |config|
        config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
      end  
    end
  end
end

You must specify the version using semantic versioning (e.g., 0.0.1).

Currently, we support the following packages:

  • TruoraCore (REQUIRED): Package for managing core functionalities of the SDK, including UI, API communication, errors and the identity process. Without this package you can’t start the SDK for your DI flow.
  • TruoraDocument (OPTIONAL): Package used when identity flow includes document validation, which contains the instructions, camera and image manipulation of the document photos.

We also require that for all common dependencies between the SDK and the client app (in the example above, marked as truora_dependencies), the flag BUILD_LIBRARY_FOR_DISTRIBUTION is set to YES. This allows the client app to compile the SDK successfully regardless of the Swift version.

Start the SDK

First, start the SDK in your code by using our core package, for example:

import TruoraCore

TDIClient.sharedInstance.startProcess(
                fromViewController: self,
                clientDelegate: delegate,
                withApiKey: apiKey
            )

To start our SDK you need to use the shared instance of TDIClient. there are three important params to take into account:

  • fromViewController: The view controller that is starting the process, it can be the component where this function is called (a.k.a self), for instance.
  • clientDelegate: A delegate that will be in charge of listening for the result (either success or errors) from the SDK. This is an object that must conform to the protocol TDIClientDelegate (check out result handling for more info).
  • withApiKey: You need to pass a generated API Key for starting the SDK flow. (Here are some instructions to create the temporary API Key and find some tips regarding its management in the API Management section)

Result handling

To handle the result of the SDK you need an object that conforms to the TDIClientDelegate protocol. This protocol has only one function for receiving the result. We will return the identity process (TDIIdentityProcess) if the process finished successfully, or a TDIError in case something failed. For example:

func processFinished(result: Result<TDIIdentityProcess, TDIError>, view: UIViewController) {
        switch result {
        case .success(let identityProcess):
            // handle identity process
            view.dismiss(animated: true, completion: <success completion>)
        case .failure(let error):
         // handle error
            view.dismiss(animated: true, completion: <error completion>)
        }
    }

Bear in mind that we return the view controller used by the SDK, so it is your responsibility to dismiss it after you have received the final result. For handling errors we recommend taking a look into the codes and respective messages for the TDIError. You can get this data by calling the getCode() and getMessage() methods of the returned object.

Requirements

  • Min SDK version: iOS 11
  • Smartphone with camera (for document validation)

Description

SDK Sizes

We used a Sample App and generated the apk with the different modules of our SDK through Android Studio, resulting in the following calculated sizes:

Application IPA download size IPA installation size
App without modules 3.1MB 8.7MB
App with Core module 3.5MB 10.2MB
App with Core and Doc module 4.5MB 13MB

The SDK sizes (IPA installation size) are as follows:

  • TruoraCore: 1.5MB
  • TruoraDocument: 2.8MB

Important Packages/Libs

  • Alamofire 5: If you are using Alamofire as well, you need at least the version 5 of this library installed.
  • Gifu 3

Tips

Camera permissions

A verification process involving document validation requires the user to take a picture of their document.

iOS will force close the app if the user changes the app's camera permissions (enable or disable) while performing the verification process in the app. To warn the user of this possible scenario and prevent them from losing their progress, we recommend you to add a message similar to the one below under the Camera Usage Description of your app's Info.plist file:

This app requires camera access to continue the verification process.

API Key Management

The code you develop for any of your mobile apps is readable. Some users can retrieve the installed IPA file, and read the code you have in there and, in case you are hardcoding secret/API keys, they might be visible. This is a high security risk, which is why we do not recommend leaving these keys hardcoded in your code.

There are multiple ways to hide your secret keys in your app, most involve leaving them in a separate server, reading from a separate file or obscuring the code itself. Some examples of these can be found in this guide.

iOS SDK Integration (WebView)

The main goal with this integration flow is to connect a mobile app with our no-code web solution located in https://identity.truora.com. Mainly we will: - Create a temporary API Key with the required configuration as shown here. - Open a webview with the url as https://identity.truora.com?token= and allow the user to complete the flow in their cellphone. - Capture the redirect event to avoid loading the specified URL and do something with the extracted data.

Webview

In the case of iOS with Swift we should use two protocols for our ViewController:

  • WKUIDelegate: Specify that the ViewController is going to be a webview and handle the loading the view
  • WKNavigationDelegate: Specify how the navigation will be handled (redirects, for example).

This config can be done in the following way:


import UIKit
import WebKit

class DIWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {
    var webView: WKWebView!
    var identityUrl: String = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        let myURL = URL(string: identityUrl)
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }

    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webConfiguration.allowsInlineMediaPlayback = true

        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        webView.navigationDelegate = self
        view = webView
    }

It’s worth noting that the URL is loaded with the “load” method of the webview.

Redirect event

For managing the redirect event we can just create a webView function that is supported since we are implementing WKNavigationDelegate:


 /// Handle navigation actions from the web view.
    func webView(_ webView: WKWebView,
        decidePolicyFor navigationAction: WKNavigationAction,
        decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

        guard let requestUrl = navigationAction.request.url else {
            // We're not being redirected, so load the URL.
            decisionHandler(.allow)
            return
        }

        // Check if we are being redirected to our `redirectUri`. This happens once verification is completed.
        let redirectUri = requestUrl.absoluteString
        guard(redirectUri.starts(with: TruoraConstants.redirectUrl)) else {
            // We're not being redirected, so load the URL.
            decisionHandler(.allow)
            return
        }

        // Capture redirect URL event at the end of the process to read data

        // At this point we're done, so we don't need to load the URL.
        decisionHandler(.cancel)

        // If we have an inquiry ID we know we have passed verification.
        // You will likely want to transition the view here to show this.
        guard let query = requestUrl.query else {
            return
        }

        print("Process ID and Account ID: " + query)
    }