- IDnowSDK
- Other Supported Platforms
- eID Framework
This document covers the integration process for the IDnow VideoIdent SDK for iOS. Public API documentation is available here.
This guide is designed for developers integrating IDnow VideoIdent SDK into iOS applications. The guide focuses on simplifying the integration process through clear instructions and practical examples.
This guide covers VideoIdent (VI) and eSign. For eID integration, please refer to this document.
Note: VI and eSign support React Native. eID requires native integration and doesn’t support React Native bridges. Use native code examples provided in this guide for integration.
IDnow VideoIdent is used to verify the identity of an individual. The user must present a supported ID document, which is matched with the ID holder or user in a process guided by an IDnow Ident Specialist. The user and the IDnow Ident Specialist interact with each other during this process using a video-chat.
IDnow offers mobile Apps for iOS and Android for user verification process. Customers can integrate VideoIdent into native mobile apps. VideoIdent can also be used with a web browser by the user.
IDnow eSign issues Qualified Electronic Signatures (QES) on one or more PDF documents. The IDnow eSign product relies on the IDnow’s VideoIdent application or the German eID technology to verify the identity of the person signing the documents. VideoIdent with eSign is available on mobile devices and web browsers; eID with eSign is only available on mobile devices due to NFC hardware limitations.
- Xcode 15 or above
- Deployment target: iOS 11+
- CocoaPods v1.13.0 or above (for the CocoaPods distribution)
- Device with WiFi/3G/LTE, camera, and microphone
Identification process requests the following permissions from the user automatically:
- Microphone
- Camera
Both are required for video identification process.
The minimum SDK version required for publishing to the App Store is now 8.0.1, following the introduction of Apple's Privacy Manifest.
VideoIdent SDK currently supports arm64
for iOS devices as well as arm64
and x86_64
simulator architectures. Please note that due to lack of camera support on the simulators we do not provide the complete flow and just mark the identification as successful not to block the testing flow.
Please refer to the following link to find information about compatibility, end-of-support (EOS) and end-of-life (EOL) dates pertaining to our products: IDnow Compatibility Matrix: Browser & OS Compatibility guide
- Add the following config and pod dependencies to your podfile:
use_frameworks!
pod 'IDnowSDK'
- Then run the following command from the project's root folder in the terminal:
pod install
- Download
idnow_vi_static.xcframework-<version>.tar.gz
from here. - Import
idnow_vi_static.xcframework
into your Xcode project. - Add the following to your project's
Link binary with libraries
section.
AudioToolbox.framework
VideoToolbox.framework
AVFoundation.framework
CoreMedia.framework
GLKit.framework
OpenGLES.framework
SystemConfiguration.framework
Webkit.framework
StoreKit.framework
Accelerate.framework
Note: To get the sample projects to work, you have to run pod install
to install dependencies.
- Download the current release from here.
- Import the
idnow_vi.xcframework
folder into your project. - Add
idnow_vi.xcframework
toEmbed Frameworks
step of your Xcode project asrequired
.
Since the release of VideoIdent SDK v7.4.1, we now support Swift Package Manager (SPM) by providing a dynamic XCFramework as a package product. For instructions on how to add the Swift package to your project, please refer to the following documentation.
- Add swift package:
https://github.com/idnow/de.idnow.ios
as dependency - Follow the regular setup described in the Usage section.
- For futher information see the spm example project
After adding the IDnowSDK into your project you need to follow these steps in order to setart an identification process.
Step 1: Import the SDK module into your source code.
import IDnowSDK
#import "IDNowSDK.h"
Step 2: Configure the appearance of the SDK. Detailed description of possible values can be found here.
let appearance = IDnowAppearance.shared()
// Adjust colors
appearance.defaultTextColor = UIColor.black
appearance.primaryBrandColor = UIColor.blue
appearance.proceedButtonBackgroundColor = UIColor.orange
appearance.checkIconColor = UIColor.red
appearance.primaryAlertActionColor = UIColor.green
// Adjust fonts
appearance.fontNameRegular = "AmericanTypewriter"
appearance.fontNameLight = "AmericanTypewriter-Light"
appearance.fontNameMedium = "AmericanTypewriter-CondensedBold"
// To adjust navigation bar / bar button items etc. you should follow Apples UIAppearance protocol.
// Setup IDnowAppearance
IDnowAppearance *appearance = [IDnowAppearance sharedAppearance];
// Adjust colors
appearance.defaultTextColor = [UIColor blackColor];
appearance.primaryBrandColor = [UIColor blueColor];
appearance.proceedButtonBackgroundColor = [UIColor orangeColor];
appearance.checkIconColor = [UIColor redColor];
appearance.primaryAlertActionColor = [UIColor greenColor];
// Adjust fonts
appearance.fontNameRegular = @"AmericanTypewriter";
appearance.fontNameLight = @"AmericanTypewriter-Light";
appearance.fontNameMedium = @"AmericanTypewriter-CondensedBold";
// To adjust navigation bar / bar button items etc. you should follow Apples UIAppearance protocol.
Step 3: Instantiate the IDnowSettings
with your companyId
and the transactionToken
obtained from the user. The complete list of settings can be found here.
let settings = IDnowSettings(companyID: "example_comp", transactionToken: "DEV-EXMPL")
IDnowSettings *settings = [IDnowSettings settingsWithCompanyID:@"example_comp" transactionToken:@"DEV-EXMPL"];
Step 4: Initialize and start the identification controller
let idnowController = IDnowController.init(settings: settings)
self.controller.initialize(completionBlock: {(success, error, canceledByUser) -> Void in
if (error != nil) {
// Handle initialization error - display an alert
}
if (canceledByUser) {
// Identification was cancelled by user
return
}
// Otherwise display the identification flow to the user
self.controller.startIdentification(from: ViewUtils.rootController(), withCompletionBlock: {(success, error, canceledByUser) -> Void in
if (error != nil) {
// Hnadle an identification error
return
}
if (canceledByUser) {
// The ident process was cancelled by the user
return
}
// Identidication was successful, proceed to the next steps in your app flow
})
})
// Initialize and start identification
IDnowController *idnowController = [[IDnowController alloc] initWithSettings: settings];
// Initialize identification using blocks
[idnowController initializeWithCompletionBlock: ^(BOOL success, NSError *error, BOOL canceledByUser)
{
if ( success )
{
// Start identification using blocks
[idnowController startIdentificationFromViewController: self
withCompletionBlock: ^(BOOL success, NSError *error, BOOL canceledByUser)
{
if ( success )
{
// identification was successfull
}
else
{
// identification failed / canceled
}
}];
}
else if ( error )
{
// Present an alert containing localized error description
UIAlertController *alertController = [UIAlertController alertControllerWithTitle: @"Error"
message: error.localizedDescription
preferredStyle: UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle: @"Ok"
style: UIAlertActionStyleCancel
handler: nil];
[alertController addAction: action];
[self presentViewController: alertController animated: true completion: nil];
}
}];
Alternatively, instead of handling the events via the callbacks you can implement the IDnowControllerDelegate
and pass it as a delegate to the IDnowViewController
.
The protocol is as follows:
/**
* Notifies the delegate
* about the success or failure of an initialization or identification.
*/
@protocol IDnowControllerDelegate
/**
* Sent to the delegate when an initialization (e.g. triggered by [IDnowController initialize]) was successfull.
*
* @param idnowController The responsible caller.
*/
- (void) idnowControllerDidFinishInitializing: (IDnowController *) idnowController;
/**
* Sent to the delegate when an initialization (e.g. triggered by [IDnowController initialize]) failed.
*
* @param idnowController The responsible caller.
* @param error The error that occurred
*/
- (void) idnowController: (IDnowController *) idnowController initializationDidFailWithError: (NSError *) error;
@optional
/**
* Sent to the delegate when an identification (e.g. triggered by [IDnowController startIdentificationFromViewController:]) was successfull.
*
* @param idnowController The responsible caller.
*/
- (void) idnowControllerDidFinishIdentification: (IDnowController *) idnowController;
/**
* Sent to the delegate when an identification (e.g. triggered by [IDnowController startIdentificationFromViewController:]) was canceled by the user.
*
* @param idnowController The responsible caller.
*/
- (void) idnowControllerCanceledByUser: (IDnowController *) idnowController;
/**
* Sent to the delegate when an identification
* (e.g. triggered by [IDnowController startIdentificationFromViewController:]) failed.
*
* @param idnowController The responsible caller.
* @param error The error that occurred.
*/
- (void) idnowController: (IDnowController *) idnowController identificationDidFailWithError: (NSError *) error;
@end
In that case, you can setup the flow like this:
let idnowController = IDnowController.init(settings: settings)
indowController.delegate = self // Conforms to IDnowControllerDelegate
idnowController.initialize()
IDnowController *idnowController = [[IDnowController alloc] initWithSettings: settings];
indowController.delegate = self; // Conforms to IDnowControllerDelegate
[idnowController initialize];
Before initializing the identification process a transactionToken
and a companyID
must be set in the IDnowSettings
. Below is an example of setting a field in the IDnowSettings
let settings = IDnowSettings()
settings.transactionToken = ident
IDnowSettings *settings = [[IDnowSettings alloc] init];
settings.transactionToken = validatedToken;
Property name | Description |
---|---|
transactionToken | A token that will be used for instantiating a video identification. The token format is XXX-XXXXX . |
companyID | Your Company ID provided by IDnow. |
environment | Optional: The environment that should be used for the identification (DEV, TEST, LIVE) The default value isIDnowEnvironmentNotDefined . The used environment will then base on the prefix of the transaction token (DEV -> DEV, TST -> Test, else -> Live). You can use the special IDnowEnvironmentCustom to define a custom environment. If this is done, you need to set the apiHost and websocketHost. See environments. |
showErrorSuccessScreen | Optional: If set to false , the Error-Success-Screen provided by the SDK will not be displayed. The default value of this property is true . |
showVideoOverviewCheck | Optional: If set to false , the Terms and Conditions screen will not be shown before starting a video identification. The default value of this property is true . |
forceModalPresentation | Optional: If set totrue , the UI for the identification will always be displayed modal. By default the value of this property is false and the identification UI will be pushed on an existing navigation controller if possible. |
apiHost | The target server url for REST calls if custom server is used. |
websocketHost | The target server url for websocket calls if custom server is used. |
connectionType | The connection type to use to talk the backend.IDnowConnectionType Possible values: - IDnowConnectionTypeWebsocket (default) - IDnowConnectionTypeLongPolling |
certificateProvider | Accepts a subclass ofIDnowCertificateProvider . Used to provide custom mTLS certificates used by the network connections. See Custom certificate providres. |
dtlsCertificateProvider | Accepts a subclass ofIDnowDtlsCertificateProvider . Used to provide custom DTLS certificates used by the WebRTC connection. See Custom certificate providres. |
To specify the environment used for the identification process, you can set a specific environment value. If no environment is defined it will be automatically determined based on the prefix of the transaction token. Usually, this is the desired behavior, so use this property only if there is a need to use the specific environment.
Available environments:
- IDnowEnvironmentDev
→ Development environments (DEV
, DEV2
, DV3
, ..., DV20
);
- IDnowEnvironmentTest
→ Test environments (TEST
, TEST1
, TEST2
, TEST3
);
- IDnowEnvironmentStag1
→ Staging environment (SG1
);
- IDnowEnvironmentLive
→ Production environment (LIVE
);
- IDnowEnvironmentCustom
→ Custom environment (CUSTOM
).
To use a custom environment following settings need to be specified as well:
let settings = IDnowSettings()
settings.apiHost = "http://\(ipAddress):\(port)"
settings.websocketHost = "http://\(ipAddress):\(port)"
settings.videoHost = "http://\(ipAddress):3000"
settings.stunHost = hostUrl
IDnowSettings *settings = [IDnowSettings sharedSettings];
settings.apiHost = [NSString stringWithFormat:@"http://%@:%@", ipAdress, port];
settings.websocketHost = [NSString stringWithFormat:@"http://%@:%@", ipAdress, port];
settings.videoHost = [NSString stringWithFormat:@"http://%@:3000", ipAdress];
settings.stunHost = [NSString stringWithFormat:HOST_URL];
For custom DTLS certificates use dtlsCertificateProvider
parameter of IDnowSettings
.
The certificate provider can be used to provide a custom DTLS certificate (featureCertificate == YES
) and/or to check the
SHA fingerprint of the server certificate (featureFingerprint == YES
).
For custom mTLS certificates use certificateProvider
parameter of IDnowSettings
.
Starting from SDK version 6.5.0 we offer mTLS support for API connections.
mTLS enables server/client certificate validation. SDK can provide custom client certificate and several server certificates.
What has changed:
- Certificate provider now can validate multiple server certificates/fingerprints
- REST supports mTLS
- WebSocket support for mTLS. For this purpose, SRWebsocket implementation was slightly updated. So, now we have a local version of SRWebsocket.
To enable mTLS, it should be available in the customer backend configuration, and client (consumer) should supply certificate provider to the SDK.
Certificate Generation:
Client certificate and private key pair can be generated in several ways, for example, with Certificate Sign Request on Mac OS X Keychain.
Client Certificates:
For iOS, key pair can be imported by platform tools from p12 package format. For example:
+ (SecIdentityRef)loadIdentityFromP12:(NSData *)p12Data password:(NSString *)password {
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { (__bridge CFStringRef)password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef p12Items;
OSStatus status = SecPKCS12Import((__bridge CFDataRef) p12Data, optionsDictionary, &p12Items);
if (status != errSecSuccess) {
return NULL;
}
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0);
SecIdentityRef identityApp = (SecIdentityRef) CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
CFRetain(identityApp);
CFRelease(optionsDictionary);
CFRelease(p12Items);
return identityApp;
}
How to do it:
1 - Create subclass of IDnowCertificateProvider
similar to IDNMyMtlsCertificateProvider
2 - During the SDK configuration step set the certificate provider:
[IDnowSettings sharedSettings].certificateProvider = [[IDNMyMtlsCertificateProvider alloc] init];
let settings = IDnowSettings()
settings.certificateProvider = IDNMyMtlsCertificateProvider()
Feature flags for certificate provider allow usage of the corresponding features:
- (BOOL)featureCertificate; // use client certificate
- (BOOL)featureFingerPrint; // use server certificate fingerprints
- (BOOL)featureServerCert; // use server certificates
You can check the certificate provider + certificates here.
Deprecated parameters (not used in VideoIdent+)
Property name | Description |
---|---|
failureColor | Optional color, that replaces the text color in the result screen, when an identification failed. Default: A red color |
successColor | Optional color, that replaces the text color in the result screen, when an identification was successful. Default: A green color |
headlineColor | Optional color, that replaces the color that will be used for headlines. Default: primaryBrandColor. Recommendation: Should be a color that does not collide with white color. |
linkColor | Optional color, that replaces the color that will be used for links. Default: primaryBrandColor. Recommendation: Should be a color that does not collide with white color. |
cqcOuterRingColor | Optional color that replaces default dark gray for the outer ring indicator on the quality check screen. Default: dark gray |
cqcDefaultInnerRingColor | Optional color that replaces default light gray for the inner ring indicator on the quality check screen. Default: light gray |
cqcPoorQualityInnerColor | Optional color that replaces default bright red for the inner ring indicator in case bad network quality on the quality check screen. Default: bright red |
cqcModerateQualityInnerColor | Optional color that replaces default bright orange for the inner ring indicator in case moderate network quality on the quality check screen. Default: bright orange |
cqcExcellentQualityInnerColor | Optional color that replaces default strong yellow for the inner ring indicator in case excellent network quality on the quality check screen. Default: strong yellow (almost green). |
enableStatusBarStyleLightContent | Optional: Forces the light status bar style to match dark navigation bars. If you tint your navigation bar with a dark color by adjusting navigation bar appearance (e.g. a blue color) you can set this value to true. The statusbar style will then be adjusted to light in screens where the navigation bar is visible. |
Using custom fonts can be observed on the appearance illustrations fo the branding section.
An optional font name that can be used to replace the regular font used by the SDK. Default: San Francisco Regular
An optional font name that can be used to replace the medium font used by the SDK. Default: San Francisco Medium
An optional font name that can be used to replace the light font used by the SDK. Default: San Francisco Light
Default: false
- Underline all button titles. Set this to true
to underline button title text
Default: true
- Make button titles bold. Set this to false
to use normal font weight in button titles
To use push notifications via the IDnow SDK it is necessary that your own AppDelegate
inherits from
the provided IDnowAppDelegate
. This is necessary because the callbacks from Apple regarding the registration and reception of push notifications are solely handled through the AppDelegate
, which is not part of our SDK. If your own IDnowAppDelegate
subclass overrides some methods, please make sure to call the superclass's implementation within your overrides.
Additionally, we will need the production certifcate/key pair to send notifications via push to your app via our backend.
// header
@interface YourAppDelegate : IDnowAppDelegate
@end
// implementation
@implementation YourAppDelegate
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
{
[super application:application didFailToRegisterForRemoteNotificationsWithError:error];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[super application:application didRegisterUserNotificationSettings:notificationSettings];
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(nonnull NSData*)deviceToken
{
[super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions
{
[super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[super application:application didReceiveRemoteNotification:userInfo];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
[super application:application didReceiveRemoteNotification:userInfo
fetchCompletionHandler:completionHandler];
}
@end
In case the identification process ends with an error a resulting callback will be passed an instance of an NSError
with a corresponding error code. The full localized description of the error can be found in the userInfo
of the error
object.
Below is the list of possible errors.
Error Code | Description |
---|---|
IDnowErrorMissingTransactionToken | Can occur during initialization (e.g. triggered by[IDnowController initialize] ). Occurs when the IDnowSettings instance does not contain a transactionToken . |
IDnowErrorMissingCompanyID | Can occur during initialization (e.g. triggered by[IDnowController initialize] ). Occurs when the IDnowSettings instance does not contain a companyID . |
IDnowErrorOfficeClosed | Can occur during initialization (e.g. triggered by[IDnowController initialize] ). Occurs when an identification cannot be initialized because the time is outside business hours. |
IDnowErrorMissingCamera | Can occur during initialization (e.g. triggered by[IDnowController initialize] ). Occurs when the device does either have no front camera or no back camera. |
IDnowErrorCameraAccessNotGranted | Can occur during initialization (e.g. triggered by[IDnowController initialize] ). Occurs when a video ident was requested, but the camera access was not granted by the user. |
IDnowErrorMicrophoneAccessNotGranted | Can occur during initialization (e.g. triggered by[IDnowController initialize] ). Occurs when a video ident was requested, but the microphone access was not granted by the user. |
IDnowErrorMissingMicrophone | Can occur during initialization (e.g. triggered by[IDnowController initialize] ). Occurs when a video ident was requested, but the device does not provide a microphone. |
IDnowErrorNoInternetConnection | Can occur during initialization (e.g. triggered by[IDnowController initialize] ). Occurs when a video ident was requested, but no internet connection is present. |
IDnowErrorServer | Can occur during initialization (e.g. triggered by[IDnowController initialize] ) and identification process (e.g. triggered by [IDnowController startIdentificationFromViewController:] ). The error object will also contain the status code returned by the server. |
IDnowErrorWebRTC | Can occur during an identification process (e.g. WebRTC service could not establish a video connection). |
IDnowErrorIdentificationFailed | Can occur during an identification process (e.g. triggered by[IDnowController startIdentificationFromViewController:] ). Describes that an identification failed. |
IDnowErrorJailbreakPhoneNotSupported | Unable to perform an identification on a jailbroken device. |
IDnowErrorInvalidWebRTCToken | Using LiveSwitch with an invalid key. |
IDnowErrorHighCallVolumeTryLater | User agreed to try the identification later due to the high call volume. |
IDnowErrorEnrolledInWaitingList | User enrolled in the Waiting List so current identification session aborted. |
IDnowErrorDeviceNotMeetPVIDRequirements | The PVID requirements only allow users with devices that support the required resolution criteria (minimum 720p: 1280 × 720 at 25 frames per second) for the VideoIdent process. |
IDnowErrorUnifiedIdentAnotherMethod | Error for a Unified Ident which states the user decided to switch to another type of identification. |
IDnowErrorTokenNotSupported_eIDStandalone | eID standalone tokens are not supported. |
IDnowErrorInvalidServerCertificate | Server trust certificate is not valid. |
IDnowErrorUnsupportedProduct | Unsupported products. |
IDnowErrorUnsupportedBluetoothHeadset | Bluetooth headset not supported. |
IDnowInstantSignDocumentExpired | INSTANT_SIGN rejected, the trusted document is expired. This document is not valid. |
In case you would like to change the localization used by the IDnow SDK at runtime you can do it by supplying the language code to the IDnowSettings
instance:
Supported values are:
Language | Code |
---|---|
English | en |
German | de |
French | fr |
Spanish | es |
Italian | it |
Portuguese | pt |
Estonian | et |
Croatian | hr |
Hungarian | hu |
Georgian | ka |
Korean | ko |
Lithuanian | lt |
Latvian | lv |
Dutch | nl |
Polish | pl |
Ukrainian | ua |
Chinese | zh |
Russian | ru |
settings.userInterfaceLanguage = @"de"; // this field accepts the following languages (de, en, it, es, pt, fr, et, hr, hu, uk, ka, ko, lt, lv, nl, pl, ru, zh).
Our Cordova plugin offers the possibility of integrating our native Android and iOS SDK into the Cordova-based applications. The plugin offers the possibility to customize and setup of the SDK. At the end of the identification process, the SDK communicates with the plug-in via a callback, allowing the Cordova application to update the flow. Please refer to this link for implementation details. Note: Only VideoIdent and eSign are supported. eID is not supported.
Our React Native plug-in offers the possibility of integrating our native Android and iOS SDK into the React Native-based applications. It offers the possibility to customize and setup the SDK, and uses the latest expo native modules to create the bridging mechanism. Please refer to this link for implementation details. Note: Only VideoIdent and eSign are supported. eID is not supported
You can find integration code examples in the examples folder.
IDnow eID is an automated and fully AML-compliant identification product. All it requires is an NFC-enabled (Near Field Communication) smartphone and a German ID document (ID card or Residence permit) with an activated eID function or the eID card for EU citizens.
For configuration details, please refer to the IDnow eID SDK Documentation