SDK for iOS 

Introduction 

The IDEMIA Verify SDK for iOS provides customers with the resources to customize the SDK to their preferred user-experience and integrate it within an existing mobile application. The IDEMIA Mobile ID Verify App works in conjunction with the IDEMIA Mobile ID App allowing verifiers to authenticate the user's physical ID or digital credential (i.e., drivers license or identity card).

You can use the iOS SDK to:

  • **Create and design your preferred user-experience and UI while leveraging the IDEMIA Verify functionalities **

    You can build a custom mobile application that implements your user-experience design and leverages all of the SDK functionalities allowing you to apply your branding and preferred user flow. Maintain complete control over the display and functionality of the application.

  • **Embed IDEMIA Verify into an existing application **

    You can automatically integrate an existing mobile application with IDEMIA by adding the SDK frameworks, which removes the need to use and maintain an additional application to leverage the Mobile ID's functionalities.


Get started 

Skills required 

The integration tasks require developers to have knowledge of:

  • iOS frameworks built in Xcode 14.2 or higher
  • Swift 5.0 or higher
  • Mac OS 12.6.2 or higher

Resources required 

The tools required for integration on macOS are:

  • Xcode 14.2 or above
  • iOS SDK tools: release 14.x to 17.x (preferably latest version)
  • Physical iOS device (simulator is not supported)

Other requirements

External Libraries

  • pod 'SwCrypt', '~> 5.1.3'
  • pod 'SwiftCBOR', '~> 0.4.3'
  • pod 'IDZSwiftCommonCrypto', '~> 0.13.0',
    => true
  • pod 'SwiftBytes', '~> 0.6.0'

User permission 

When designing your app,consider that your iOS app must handle user permissions to protect the resources on the target mobile device. Specifically, you must verify that the app permissions are granted by the user. If the required permissions are not granted, the SDK will throw an exception or error and may even crash.

The following user permission are required:

  • Camera permission for the QR code scan
  • Bluetooth permission for the BLE data transfer
  • NFC permission for the device engagement

The required permissions in the app info.plist file are:

  • Privacy: Bluetooth Always Usage Description
  • Privacy: Bluetooth Peripheral Usage Description
  • Privacy: Camera Usage Description
  • Privacy: NFC Usage Description

Capability 

If the integrator wants to use NFC as Device Engagement.

The following steps are required:

Project Target -> Signing & Capabilities -> + Capability -> Near Field Communication Tag Reading


Create your own app 

If you already have access for Mi-Artifactory, download the sample app: https://mi-artifactory.otlabs.fr/artifactory/verify-sdk-ios-release/com/idemia/idverify/ios/3.7.0/Sample/3.7.0-sample-ios.zip

To create your own app, you must add the following SDK libraries to your project. You can add these libraries manually as shown in Option A, or through CocoaPods as shown in Option B.

Add SDK libraries 

The Podfile specifies the dependencies of each target, and the SDK pods are used to declare a specific dependency. The target scopes the pod dependencies to specific targets in your Xcode project.

Required pods

  • pod 'SwCrypt', '~> 5.1.3'
  • pod 'SwiftCBOR', '~> 0.4.3'
  • pod 'IDZSwiftCommonCrypto', '~> 0.13.0',
    => true
  • pod 'SwiftBytes', '~> 0.6.0'

Option A: Import Verify SDK manually

The manual method allows you to import the SDK files using Verify.framework using the steps below:

  1. Download the Verify.framework and Tester app from the mi-artifactory: https://mi-artifactory.otlabs.fr/artifactory/verify-sdk-ios-release/com/idemia/idverify/ios/

  2. Add the Verify.framework file to your project by pasting this file in project folder at path: ~/Frameworks/Verify.framework.

  3. Link and Embedd Verify.framework to your project by dragging and dropping it on Project Settings (General > Frameworks, Libraries, and Embedded Content).

  4. At the top of your project Podfile add the lines shown in the snippet:

    Swift
    1plugin 'cocoapods-art', :sources => [
    2 'master' # so it could resolve dependencies from master repo (the main one)
    3]
  5. Add following pod dependency (Follow the 1,2 steps from section Option B for repository access)

  • pod 'SwCrypt', '~> 5.1.3'
  • pod 'SwiftCBOR', '~> 0.4.3'
  • pod 'IDZSwiftCommonCrypto', '~> 0.13.0',
    => true
  • pod 'SwiftBytes', '~> 0.6.0'
  1. Add the following line in end of your Podfile (refer the sample code) to avoid linker error of any pod dependencies of Verify.

    Swift
    1post_install do |installer|
    2 installer.pods_project.targets.each do |target|
    3 target.build_configurations.each do |config|
    4 config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
    5 end
    6 end
    7 end

Option B: Import Verify SDK through CocoaPods with other dependencies (Recomended option)

Alternatively, the CocoaPods method allows you import the SDK files using CocoaPods (along with cocoapods-artplugin) using these steps.

  1. If you don't already have CocoaPods with the Artifactory tool, install it by running the following command as shown in the snippet:

    Swift
    1gem install cocoapods-art
  2. The plugin uses authentication that is specified in a standard .netrc file, as shown in the snippet:

    Swift
    1machine mi-artifactory.otlabs.fr
    2login ##USERNAME##
    3password ##PASSWORD##
  3. At the top of your project Podfile add the lines shown in the snippet:

    Swift
    1plugin 'cocoapods-art', :sources => [
    2 'verify-sdk-ios-release', # so it could resolve dependencies for Verify
    3 'master' # so it could resolve dependencies from master repo (the main one)
    4]

NOTE: If you do not have podfile already created, use the following commands to create one

Swift
1pod init
  1. Once set, add our repository to your CocoaPod's dependency management system as shown in the snippet:

    Swift
    1pod repo-art add verify-sdk-ios-release "https://mi-artifactory.otlabs.fr/artifactory/api/pods/verify-sdk-ios-release"
  2. Add the Verify SDK in your Podfile in one of its pod's version, as shown in the snippet:

    Swift
    1pod 'Verify', '~> 3.7.0.1462' # Verify SDK
  3. Now install or install as shown in the snippet:

    Swift
    1pod install or pod update

    NOTE: If you are already using our repository, and you cannot resolve some dependency, try to update the specs:

    Swift
    1pod repo-art update verify-sdk-ios-release
  4. Add the following line in end of your Podfile (refer the sample code) to avoid linker error of any third party dependencies of Verify.

    Swift
    1post_install do |installer|
    2 installer.pods_project.targets.each do |target|
    3 target.build_configurations.each do |config|
    4 config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
    5 end
    6 end
    7 end

SDK API’s and methods 

The SDK is made up of following components:

API’s for Version V1 

  1. IDVerifyTerminal Acts as the Entry Point for initializing device engagement, sending request to Mobile ID holder, receiving response and send parsed model back to calling app

    • initDeviceEngagement
Language not specified
1/* Call this method from UI Application to parse the scanned qrcode
2 - @param configParams: Send the parameters e.g. inputData, license attribute params e.g. AGE_OVER_NN
3 - @param responseCallback: callback to receive the model object/errors corresponding to the passed-in QRCode
4 */
5 public func initDeviceEngagement(apiConfig configParams: ApiConfigs?, responseCallback: UIViewController)
  • sendRequest
Language not specified
1/* Send request to Mobile ID based on the use case selected by user in Verify application
2 - @param apiConfigs: configurations and optional MID request params
3 - @param callback: callback to send progress and response data back to app
4 - 1. create Mobile ID request based on supplied USECASE or parameres/configs
5 - 2. onCreate communication channel (BLE) as per engagement data
6 - 3. send request to Mobile ID on communication chanel
7 - Note- In future we may also use USECASE : use case identifier required to prepare desired request data
8 */
9 public func sendRequest(apiConfig configParams: ApiConfigs?, responseCallback: UIViewController)
  • cancelRequest
Language not specified
1/* Cancel any transaction/running session with Mobile ID. overload to default cancellation
2*/
3public func cancelRequest(responseCallback: UIViewController, cancellationReason: CancellationReason)
  • loadCertificates
Language not specified
1/* Load IACA certificates from given path by application
2 - @param path is the Directory (libraryDirectory type) folder name(created by integrator)from where SDK will load the certificate, refer the sample.
3 - @param responseCallback is callback to return success(will return loaded certificate count) or error
4 */
5 public func loadCertificates(path: String?, responseCallback: Any)

API’s for Version V2 (Recomended) 

  1. IDVerifyTerminalV2 Acts as the Entry Point for initializing device engagement, sending the request, by preparing a connection to the Mobile ID holder, receiving a response, and sending parsed model back to the calling app

    • initDeviceEngagement
Language not specified
1/* Call this method from UI Application to parse the scanned qrcode
2 - @param configParams: Send the parameters e.g. inputData, license attribute params e.g. AGE_OVER_NN
3 - @param responseCallback: callback to receive the model object/errors corresponding to the passed-in QRCode
4 */
5 public func initDeviceEngagement(apiConfig configParams: ApiConfigs?, responseCallback: UIViewController)
  • prepareConnection
Language not specified
1/* Initialize and setup connection components as per`ConnectionConfigs` configurations supplied
2 - @param configParams: configurations for connection related information
3 - @param callback: callback to connection status back to app
4 - Create communication channel (BLE) as per device engagement data
5 */
6 public func prepareConnection(configParams: ConnectionConfig?, responseCallback: (Any)?)
  • sendRequest
Language not specified
1/* send request to Mobile ID based on the use case selected by user in Verify application
2 - @param apiConfigs: configurations and optional MID request params
3 - @param callback: callback to send progress and response data back to app
4 - 1. create Mobile ID request based on supplied USECASE or parameres/configs
5 - 2. onCreate communication channel (BLE/NFC/wifiAware ...) as per engagement data
6 - 3. send request to Mobile ID on communication chanel
7 - Note- In future we may also use USECASE : use case identifier required to prepare desired request data
8 */
9 public func sendRequest(apiConfig configParams: ApiConfigs?, responseCallback: UIViewController)
  • terminateConnection
Language not specified
1/* Terminate connection available with Mobile ID.
2 - @param responseCallback: callback to receive the model object/errors corresponding to the passed-in qrcode
3 - @param cancellationReason: Send the enum of cancellationReason e.g. TIMEOUT, CANCELED_BY_USER, CONNECTION_ERROR and NONE
4 */
5 public func terminateConnection(responseCallback: Any?, cancellationReason: CancellationReason)
  • terminateSession
Language not specified
1/* It terminate the current session and terminate the connection as well.
2 - @param responseCallback: callback to receive the model object/errors corresponding to the passed-in qrcode
3 - @param cancellationReason: Send the enum of cancellationReason e.g. TIMEOUT, CANCELED_BY_USER, CONNECTION_ERROR and NONE
4 */
5 public func terminateSession(responseCallback: Any?, cancellationReason: CancellationReason)
  • loadCertificates
Language not specified
1/* Load IACA certificates from given path by application (libraryDirectory path)
2 - @param path is the Directory (libraryDirectory type) folder name(created by integrator)from where SDK will load the certificate, refer the sample.
3 - @param responseCallback is callback to return success(will return loaded certificate count) or error
4 */
5 public func loadCertificates(path: String?, responseCallback: Any)

Api implementation steps 

  1. Scan the QR codes or NFC Tags as shown in the snippet:

    Swift
    1/**
    2 * Response callback for parse engagement QR code data or **Mobile ID** credential holder
    3 */
    4 //MARK: parsed QRCode
    5 func parsedDataForQRCode(trimmedQRCode: String){
    6 DispatchQueue.global(qos: .default).asyncAfter(deadline: .now() + 0.2) {
    7 let config = self.formAndReturnAppConfigsParamForAPI(qrString: trimmedQRCode)
    8 sharedVSDKClient?.initDeviceEngagement(apiConfig: config, responseCallback: self)
    9 }
    10 }
    11
    12 // Returns ApiConfigs with all the parameters
    13 func formAndReturnAppConfigsParamForAPI(qrString qr: String?) -> ApiConfigs? {
    14 guard let tempQRString = qr else {
    15 return nil
    16 }
    17
    18 // Build app configs for BLE
    19 let apiConfigs = ApiConfigs.ConfigBuilder()
    20 .withData(inputData:tempQRString)
    21 .build()
    22 return apiConfigs
    23
    24 // Build app configs for NFC Engagement
    25 let apiConfigs = ApiConfigs.ConfigBuilder()
    26 .useNFC()
    27 .build()
    28 return apiConfigs
    29 }
  2. After scanning the QR successfully, you will get the result response in onSuccess as shown in the snippet:

    Swift
    1func onSuccess(response: Any?){
    2 }
    3 func onError(error: VerifyError){
    4
    5 }
  3. For V2 API’s, call prepareConnection API before calling sendRequest (in case of V1 API’s skip to step 4.1).

The prepareConnection() method will prepare the connection based on device engagement with Mobile ID credential. If it received successfully, Integrator can send the request on prepared connection channel.

Swift
1// Set 'ConnectionConfig' as follows for setting the connection related information.
2
3let connectionConfig = ConnectionConfig()
4 .setConnectionType(type: ConnectionType.BLE)
5 sharedVSDKClient?.prepareConnection(configParams: connectionConfig, responseCallback: self)
Swift
1// Set 'setL2CapRequestSupport' as true to enable L2CAP mode during BLE communication.
2
3let connectionConfig = ConnectionConfig()
4 .setConnectionType(type: ConnectionType.BLE)
5 .setL2CapRequestSupport(l2CapRequestSupportEnable: true)
6 sharedVSDKClient?.prepareConnection(configParams: connectionConfig, responseCallback: self)
Swift
1// prepareConnection api by using `connectionConfig` which you set earlier
2sharedVSDKClient?.prepareConnection(configParams: connectionConfig, responseCallback: self)

Callback for the prepareConnection API to receive connection status**.

Swift
1/**
2 * Request callback for the `prepareConnection` SDK API to receive connection status.
3 */
4
5 func connectionSuccessful(connectionType: ConnectionType) {
6 }
7
8 func connectionError(error: Any?) {
9 }
10
11 func currentStatus(currentState: TransferState){
12 }
13
14 func onConnectionCanceled(response: Any?) {
15 }
  1. Send a request to the Mobile ID App to get the license details as shown in the snippet:

The sendRequest() method will return the response from the end-user's Mobile ID credential. If it's received it successfully, then all the attributes of the Mobile ID App response appear in the view controller.

Swift
1// Set 'appConfig' as follows if you want to use all attributes as optional parameters
2var dataItems = getMandatoryParams()
3dataItems.append(contentsOf: getOptionalParams())
4
5let apiConfigs = AppConfigs.MIDRequestBuilder()
6            .addParam(listParams: dataItems)
7            .build()
Swift
1// Set 'appConfig' as follows if you want to use only the suggested attributes as optional parameters
2var dataItems = getOptionalParams() let apiConfigs =
3AppConfigs.MIDRequestBuilder() .addParam(listParams: paramsList, useDefaults:
4true) .build()
Swift
1//Send the request by using `appConfig` which you set earlier
2sharedVSDKClient?.sendRequest(apiConfig: apiConfigs, responseCallback: self)
3}
Swift
1// Sample code for L2Cap Support in Api config. Set L2CapRequestSupportEnable as true for enabling L2cap support.
2let apiConfigs = ApiConfigs.MIDRequestBuilder()
3 .version(version: MIDParamConstants.REQUEST_VERSION)
4 .setL2CapRerquestInfo(L2CapRequestSupportEnable: true)
5 .addParams(MIDParamConstants.NAMESPACE_18013_5,isoParamsList)
6 .build()
Swift
1// send request using new namespace and paramList support
2
3func sendrequest(){
4
5 var aamvaParamsList = [MIDRequestParam]()
6 var namespaceParamList = [String: [MIDRequestParam]]()
7 var isoParamsList = [MIDRequestParam]()
8 isoParamsList.append(MIDRequestParam(paramName: MIDParamConstants.GIVEN_NAME))
9 isoParamsList.append(MIDRequestParam(paramName: MIDParamConstants.FAMILY_NAME))
10 isoParamsList.append(MIDRequestParam(paramName: MIDParamConstants.RESIDENT_ADDRESS))
11 isoParamsList.append(MIDRequestParam(paramName: MIDParamConstants.RESIDENT_CITY))
12 isoParamsList.append(MIDRequestParam(paramName: MIDParamConstants.RESIDENT_CITY))
13
14 namespaceParamList[MIDParamConstants.DOCTYPE_ORG_AAMVA_US] = aamvaParamsList
15 namespaceParamList[MIDParamConstants.NAMESPACE_18013_5 ] = isoParamsList
16
17 let apiConfigs = ApiConfigs.MIDRequestBuilder()
18 .version(version: MIDParamConstants.REQUEST_VERSION)
19 .addDocType(docType: "my.cusom.docType.custom1") //example docType1
20
21 //1. add
22 .addParams(namespaceParamList)
23 // add again to test if duplicates are removed
24 .addParams(MIDParamConstants.NAMESPACE_18013_5,isoParamsList)
25 //2. add more params one by one with custom namespce
26 .addParam(MIDParamConstants.NAMESPACE_18013_5,MIDRequestParam(paramName: "custom_param1"))
27 .addParam("my.custom.namespace",MIDRequestParam(paramName: "custom_param1"))
28
29 .addParam("my.custom.namespace",MIDRequestParam(paramName: "custom_param2"))
30 .addParam("my.custom.namespace",MIDRequestParam(paramName: "custom_param3"))
31 //duplicates will be removed
32 .addParam("my.custom.namespace",MIDRequestParam(paramName: "custom_param1"))
33 .addParam("my.custom.namespace",MIDRequestParam(paramName: "custom_param3"))
34 //3. or add a custom namespace like this
35 .addParams("my.custom.namespace2", [
36 MIDRequestParam(paramName: "custom_param_nm21"),
37 MIDRequestParam(paramName: "custom_param_nm22"),
38 MIDRequestParam(paramName: "custom_param_nm23"),
39 MIDRequestParam(paramName: "custom_param_nm21") ]//duplicate
40 )
41
42 .buildDoc() //build doctype1
43 .addDocType(docType: "my.cusom.docType.custom2") //example docType2
44 .addParams("my.custom.namespace2", [
45 MIDRequestParam(paramName: "custom_param_nm21"),
46 MIDRequestParam(paramName: "custom_param_nm22"),
47 MIDRequestParam(paramName: "custom_param_nm23"),
48 MIDRequestParam(paramName: "custom_param_nm21") ]//duplicate
49 )
50 .buildDoc() //build doctype2
51
52 .build()
53
54 //call sendRequest API
55 sharedVSDKClient?.sendRequest(apiConfig: apiConfigs, responseCallback: self)
56 // 3. Read request params supplied from app and make the request structure accordingly.
57
58}
  1. Callback for the sendRequest API to receive and display the response data from the Mobile ID App.
Swift
1/**
2 * Request callback for the `sendRequest` SDK API to receive and display the response data from the mDL.
3 */
4
5 func onSuccess(response: Any?){
6 }
7 func onError(error: VerifyError){
8 }
9 func onRequestCanceled(response: Any?){
10 }
11 func onProgress(totalBytesRecived: Int){
12 }
13 func onRequestSent(status: Bool?){
14 }
15 func currentBLEStatus(currentState: TransferState){
16 }
17
18 // onSuccess callback method for handling Multi request reqsponse
19 func onSuccess(response: Any?, callback:MultiRequestCallback?) {
20 }
21
22 // On next callback is used for sending next request in same session.
23 func onNext(apiConfigs:ApiConfigs){
24 }
25
26 // Terminate connection method is used for terminate session in Multirequest.
27 func onTerminateConnection() {
28 }
29
30 /**Set Multi Request Info.
31 - Parameter multiRequestEnable: Set for identify request is Multi Request supported
32 - Returns: MIDRequestBuilder object
33 */
34 public func setMultiRerquestInfo(multiRequestEnable: Bool) -> MIDRequestBuilder {
35 self.isMultiRequest = multiRequestEnable
36 return self
37 }
38
39 // Sample code for multi request Api config
40 let apiConfigs = ApiConfigs.MIDRequestBuilder()
41 .version(version: MIDParamConstants.REQUEST_VERSION)
42 .setMultiRerquestInfo(multiRequestEnable: VerifyAppManager.sharedInstance.getMultiRequestMode() ?? false)
43 .addDocType(docType: MIDParamConstants.DOCTYPE_18013_5)
44 .addParams(MIDParamConstants.NAMESPACE_18013_5,isoParamsList)
45 .addParams(MIDParamConstants.NAMESPACE_ORG_AAMVA_US,aamvaParamsList)
46 .addRequestInfo(key: "attributesInfo", value: attributeInfoMap())
47 .build()

Step and sample code for Reader Authentication(Signature only)[optional].

11. Add/Enable the callback in the RequestBuilder.
2
32. Implement the readerAuthSignerCallback at app side. readerAuthSignerCallback provides the interface to perform signing of readerAuthentication structure. Verify SDK will call doSignRequest with the readerAuthentication structure to sign by the integrator with the reader private key. They will sign the bytes using certificate private key and return ReaderAuthSign data model with generated signature, algorithm used to sign and a x509 certificate with the corresponding public key of the private key that the readerAuthenticationBytes structure is signed.[Refer 9.1.4 mdoc reader authentication ISO/IEC FDIS 18013-5:2021(E) page 54]
4
53. List the required resources e.g cert, keys at Integrator side.
6An mdocReader private key to sign the Reader Auth structure. the resulting signature and algorithm used to sign shall be included within the mdoc request to be sent to mdoc.
7CA signer certificate containing the corresponding public key of the private key used in signing which shall be sent to mdoc within the mdoc request. Integrator would submit a CSR to a valid CA to get a signer certificate.
8(Optional) CA root certificate from CA which shall be shared by Reader to mDoc Holder which they can use to authenticate the signer certificate received within Reader Request
  1. You can cancel / terminate a transaction any time if an error occurs in the app as shown in the snippet:
Swift
1sharedVSDKClient?.cancelRequest(responseCallback: self,cancellationReason: .CANCELED_BY_USER)

For V2 API’s

Swift
1sharedVSDKClient?.terminateConnection(responseCallback: Any?, cancellationReason: CancellationReason)

6.1. To terminate the running connection and session use terminateSession API. This API is available only in IDVerifyTerminalV2 client

Swift
1sharedVSDKClient?.terminateSession(responseCallback: Any?, cancellationReason: CancellationReason)
  1. You can get the SDK version by calling it directly with the class name as shown in the snippet:
Swift
1IDVerifyTerminal.version

For V2 API’s

Swift
1IDVerifyTerminalV2.version
  1. Added new configuration setReaderAuthInfo for reader authentication; here is a sample code snippet:

    Swift
    1let apiConfigs = ApiConfigs.MIDRequestBuilder()
    2 .version(version: MIDParamConstants.REQUEST_VERSION)
    3 .addDocType(docType: "org.iso.18013.5.1.mDL")
    4 .addParams(namespaceParamList)
    5 .buildDoc()
    6 .setReaderAuthInfo(readerAuthSignerCallback: self.callbackReceiverVC, signingAlgo: .ALGO_SHA256WITHECDSA)
    7 .withData(inputData: MOCK_QR_CODE_DATA_N1938)
    8 .build()
  2. Added new protocol ReaderAuthSignerCallback for reader authentication callback; here is a sample code snippet of implementation:

    Swift
    1extension ViewController: ReaderAuthSignerCallback {
    2 func doSignItemRequest(readerAuthenticationBytes: Data, docType: String) -> ReaderAuthSign? {
    3 //Generating Public Private KeyPair
    4 let keyPairDict = try? ECUtils.generateKeyPair()
    5 let privateKey = keyPairDict?["private"]
    6 //Generating Signature
    7 let signedDataSignature = (try? EncyptionDecryption.createSignature(privateKey: privateKey, dataToSign: readerAuthenticationBytes, algorithm: .ecdsaSignatureDigestX962SHA256)) ?? Data()
    8 //returning Signature and Certificate
    9 return ReaderAuthSign(signature: signedDataSignature, x509Certificate: x509CertSample.bytes.getData())
    10 }
    11}
  3. Call loadCertificates() API to load IACA certificates from given path(libraryDirectory path) and provides the number of certificats loaded as response(Int). This step is necessary for a successful transaction since Verify SDK will validate the mDL response against the certificates from supplied path. Refer sample Application.

Swift
1sharedVSDKClient?.loadCertificates(path: "CERTIFICATEDIRECTORY_NAME", responseCallback: self())
2 func onSuccess(response: Any?){
3 print("Certificate load success \(response)")
4 }
5 func onError(error: Any?){
6 print(error)
7 }
  1. Call setDisconnectBleTimeout() method to set BLE disconnect timeout time from app side. Default timeout is 3 sec.
Swift
1let sharedClient = self.getVerifySDKClient()
2 let configs = ApiConfigs.ConfigBuilder().withData(inputData: "").useBLE().setDisconnectBleTimeout(time: 5).build()

Test and production apps 

The Verify SDK allows you to create a test app with the steps below. You can also use these steps to create your production application by changing the target definition in your Podfile to your Xcode production project.

  1. Open your terminal and type the command "cd project_path" (the path to the project file where .xcodeproj file is located) and press .

  2. Type the command "pod init" and press .

  3. Go to the finder and open the pod file (in the same place where your .xcodeproj file is located).

  4. Type the following in podfile under your target. In our case, the target is VerifyIDTestApp; change it according to your target in podfile and add the snippet shown:

    Language not specified
    1target 'VerifyIDTestApp' do
    2 use_frameworks!
    3 pod 'Verify', '~> 3.7.0.1462'
    4
    5 target 'VerifyIDTestAppTests' do
    6 inherit! :search_paths
    7 # Pods for testing
    8 end
    9
    10 target 'VerifyIDTestAppUITests' do
    11 # Pods for testing
    12 end
  5. Type the command “pod install” and then press .

  6. Open .xcworkspace (i.e., at the same place where your .xcodeproj file is located).

  7. Call IDVerifyTerminal.getClient and initialize the IDVerifyTerminal shared object in the AppDelegate.swift file as shown in the snippet:

For V2 API’s Call IDVerifyTerminalV2.getClient and initialize the shared object of IDVerifyTerminalV2 in AppDelegate.swift file**

1let config = Configs.Builder()
2 .enableDebug(isDebuggable: isDebuggable)
3 .build()
4 **For V1 API’s-**
5 sharedVSDKClient = IDVerifyTerminal.getClient(configs: config)
6 **For V2 API’s-**
7 sharedVSDKClient = IDVerifyTerminalV2.getClient(configs: config)
  1. Use enableDebug(logLevelArr: [LogLevel.VERBOSE]) for debugging purposes only if needed, as shown in the snippet:

    Swift
    1let config = Configs.Builder()
    2 .enableDebug(logLevelArr: [LogLevel.VERBOSE]) // multiple option can be passed. Default is LogLevel.NONE
    3 .build()
    4
    5
    6 **For V1 API’s-**
    7 sharedVSDKClient = IDVerifyTerminal.getClient(configs: config)
    8 **For V2 API’s-**
    9 sharedVSDKClient = IDVerifyTerminalV2.getClient(configs: config)

Request Parameters 

The following table provides a list of attributes which can be configured for sendRequest API.

Item#
Identifier
Param Name
CBOR Type
Namespace= "org.iso.18013.5.1"
1ADMINISTRATIVE_NUMBERadministrative_numberMajor type 3
2SEXsexMajor type 3
3HEIGHTheightMajor type 0
4WEIGHTweightMajor type 0
5EYE_COLOReye_colorMajor type 3
6HAIR_COLORhair_colorMajor type 3
7BIRTH_PLACEbirthplaceMajor type 3
8RESIDENT_ADDRESSresident_addressMajor type 3
9PORTRAIT_CAPTURE_DATEportrait_capture_dateTag value 0 of major type 6
10AGE_IN_YEARSage_in_yearsMajor type 0
11AGE_BIRTH_YEARage_birth_yearMajor type 0
12AGE_OVER_NNage_over_NNValue 20/21 of major type 7
13ISSUING_JURISDICTIONissuing_jurisdictionMajor Type 3
14NATIONALITYnationalityMajor type 3
15RESIDENT_CITYresident_cityMajor type 3
16RESIDENT_STATEresident_stateMajor type 3
17RESIDENT_POSTAL_CODEresident_postal_codeMajor type 3
18BIOMETRIC_TEMPLATE_XXbiometric_template_xxMajor type 2
19NAME_NAT_CHARname_nat_charMajor type 3
20MGMT_NEXT_UPDATEmgmt_nextupdateTag value 0 of major type 6
21FAMILY_NAMEfamily_nameMajor type 3
22GIVEN_NAMEgiven_nameTag value 0 of major type 6
23BIRTHDATEbirthdateTag value 0 of major type 6
24ISSUE_DATEissue_dateTag value 0 of major type 6
25EXPIRY_DATEexpiry_dateMajor type 3
26ISSUING_COUNTRYissuing_countryMajor type 3
27ISSUING_AUTHORITYissuing_authorityMajor type 3
28DOCUMENT_NUMBERdocument_numberMajor type 3
29PORTRAITportraitMajor type 2
30MGMT_LAST_UPDATEmgmt_lastupdateTag value 0 of major type 6
31MGMT_VALIDITYmgmt_validityTag value 0 of major type 6
32ONLINE_TOKEN_XXXXonline_token_xxxxMajor type 3
34DRIVING_PRIVILEGESdriving_privilegesMajor type 4
35SIGNATURE_USUAL_MARKsignature_usual_markMajor type 3
36ONLINE_URL_XXXXonline_url_xxxxMajor type 3
37BIRTHDATEbirth_dateMajor type 3
38BIRTH_PLACEbirth_placeMajor type 3
39NAME_NAT_CHARname_national_characterMajor type 3
40FAMILY_NAME_NATIONAL_CHARfamily_name_national_characterMajor type 3 //added in N19xx
41GIVEN_NAME_NATIONAL_CHARgiven_name_national_characterMajor type 3 //added in N19xx
Namespace= "org.iso.18013.5.1.aamva"//based on mDL-Implementation-Guidelines-1-0_2021.pdf
1DOMESTIC_DRIVING_PRIVILEGESdomestic_driving_privilegesMajor type 3
2DHS_COMPLIANCEDHS_complianceMajor type 3
3NAME_SUFFIXname_suffixMajor type 3
4ORGAN_DONORorgan_donorMajor type 0
5VETERANveteranMajor type 0
6FAMILY_NAME_TRUNCATIONfamily_name_truncationMajor type 3
7GIVEN_NAME_TRUNCATIONgiven_name_truncationMajor type 3
8AKA_FAMILY_NAME_V2aka_family_name.v2Major type 3
9AKA_GIVEN_NAME_V2aka_given_name.v2Major type 3
10AKA_SUFFIXaka_suffixMajor type 3
11WEIGHT_RANGEweight_rangeMajor type 0
12RACE_ETHNICITYrace_ethnicityMajor type 3
13EDL_CREDENTIALEDL_credentialMajor type 0
14SEXsexMajor type 0
15RESIDENT_COUNTYresident_countyMajor type 3
16HAZMAT_ENDORSEMENT_EXPIRATION_DATEhazmat_endorsement_expiration_dateMajor type 3
17DHS_TEMPORARY_LAWFUL_STATUSDHS_temporary_lawful_statusMajor type 0

Expected Results 

QR code

Below are expected response from the sendRequest API with the expected data type.

Data Fields
Data type/Unit
Sample Value
Namespace= "org.iso.18013.5.1"
administrative_numberText/String"1234453"
genderText/String"M"
heightInteger/Centimeter"157"
weightInteger/Kg"56"
eye_colorText/String"BLU"
hair_colorText/String"BLACK"
birthplaceText/String"NY"
resident_addressText/String"123, ABC Street"
portrait_capture_dateDateTime/RFC3339"1985-04-12T23:20:50Z"
age_in_yearsInteger/String"34"
age_birth_yearInteger/String"1978"
age_over_NNBoolean/String"true"
issuing_jurisdictionText/String"NY"
nationalityText/String"US"
resident_cityText/String"NY"
resident_stateText/String"NY"
resident_postal_codeText/String"58773"
name_nat_charText/String"US"
mgmt_nextupdateDateTime/RFC3339"1985-04-12T23:20:50Z"
family_nameText/String"Sample"
given_nameText/String"Joe"
birthdateDateTime/RFC3339"1985-04-12T23:20:50Z"
issue_dateDateTime/RFC3339"1985-04-12T23:20:50Z"
expiry_dateDateTime/RFC3339"1985-04-12T23:20:50Z"
issuing_countryText/String"US"
issuing_authorityText/String"NY"
document_numberInt/String"782593823"
portraitByteArray/Bytes
mgmt_lastupdateDateTime/RFC3339"1985-04-12T23:20:50Z"
mgmt_validityDateTime/RFC3339"1985-04-12T23:20:50Z"
driving_privilegesText/String"[{"codes":[{"sign":"Sign","value":"value","code":"C"}],"issue_date":"2018-08-09","vehicle_category_code":"A","expiry_date":"2024-06-11"}]"
RealIDBoolean/Stringtrue
signature_usual_markByteArray/Bytes
birth_dateDateTime/RFC3339"1985-04-12T23:20:50Z"
birth_placeText/String"NY"
name_national_characterText/String"US"
given_name_national_characterText/String"US"
family_name_national_characterText/String"US"
Namespace = "org.iso.18013.1.aamva"
DHS_complianceText/String“F” = fully compliant “N” = non-compliant
domestic_driving_privilegesText/String[{"domestic_vehicle_class": {"expiry_date": "2027-08-12", "issuer_date":"2019-10-12", "domestic_vehicle_class_code": "A", "domestic_vehicle_class_description": "vehicle category description"}, "domestic_vehicle_endorsements": [{"domestic_vehicle_endorsement_code": "E", "domestic_vehicle_endorsement_description": "vehicle endorsement description"}], "domestic_vehicle_restrictions": [{"domestic_vehicle_restriction_code": "C", "domestic_vehicle_restriction_description": "vehicle restrictions description"}]}]
name_suffixText/String“SR”
organ_donorInteger1
veteranInteger1
family_name_truncationText/String“N”
given_name_truncationText/String“N”
aka_family_name.v2Text/String“N”
aka_given_name.v2Text/String“S”
aka_suffixText/String“N”
weight_rangeInteger“3” //Indicates the approxi- mate weight range of the credential holder: 0 = up to 31 kg; 1 = 32 – 45 kg ; 2 = 46 - 59 kg ; 3 = 60 - 70 kg
race_ethnicityText/String“A” //Codes for race or eth- nicity of the creden- tial holder, as defined in AAMVA D20.
EDL_credentialInteger1 //This field is either absent or has one of the following values: 1: Driver’s license, 2: Identification card (Applicable only in the US. )
sexInteger1
resident_countyText/String"107" //The 3-digit county code of the county where the credential holder lives, as per the 2010 FIPS Codes for Counties and County Equivalent Entitiesf. (Applicable only in the US. )
hazmat_endorsement_expiration_dateText/String"2024-01-11"
DHS_temporary_lawful_statusInteger1 // This field is either absent or has value= 1: Temporary lawful status (Applicable only in the US. )

IACA certificate file format support 

  • Supports following formats for IACA certificates - (.pem, .crt, .der).

Elliptic curve support 

Operation
Curve
Specification
Curve Identifier
ECDH/ECDSAP-256FIPS-PUB 186-4IANA COSE Registry
ECDH/ECDSAP-384FIPS-PUB 186-4IANA COSE Registry
ECDH/ECDSAP-521FIPS-PUB 186-4IANA COSE Registry

ISO-18013-5 specification support 

ISO Version
Supported
N1985 (published 1.0)Yes
N1938Yes
N1818Yes
N1677Yes

Additions and updates 

  • Removal of OpenSSL Dependency
  • Added support of CryptoKit
  • Added iOS 17 support
  • Dropping iOS 13 support
  • Load certificate from Library directory
  • Bug fixes and improvements

Notes:

  • IDEMIA has many IACA certificates added to our Verify App, so we must categorize these certificates, such as Production, Demo, UAT, in our App. This allows the Verify App integrator to know which certificate matches pertain to which environment at any time during a transaction.
  • A certificate validation match is performed with the Mobile ID credential, and a certification tag is created for every certificate. This flag is used used in the Verify SDK to distinguish between different purposes of the certifications, leading to indicators in the Verify App results screen that some Mobile IDs credentials are “Not for Official Use”. If a certificate is not in production, then it is not meant for official use.
  • A popup/updated UI on the Verify App displays whether the Mobile ID credential is applicable for official use or not, based on the matched IACA certificate. Currently, for integrators, this provides additional information for IACA certificate matching.
  • The classification of these certificates is shown in this link: https://idemiadigitallabs.atlassian.net/wiki/spaces/MI/pages/478052581/IACA+Certificates
  • Verify SDK support following file formats for IACA certificates - (.pem, .crt, .der)
  • NFC implementation for Device Engagement (It only supports Static Device Engagement)

Error codes 

This table contains the list of data error codes, messages, descriptions, and actions required.

Error Code
Error Code Message
Description
Action Required
101Invalid QR CodePlease try again.Try Again.
102QR Data item is missing or found any issueIf item type is not as expected.Try Again.
103QR Data item is missing or found any issueIf DataItem(Map) is empty.Try Again.
104QR Data item is missing or found any issueIf DataItem(Array) is empty.Try Again.
105QR code scan errorUnable to Scan QR code may be because of invalid data or bad encoding.Try Again.
111Invalid EDeviceKeyNot supported or unspecified curve Id in DeviceEngagement structure sent by the mdocTry Again
123Parsing ErrorError in compact mode qr code parsing and verificationTry Again.
124Image Conversion ErrorError in convert image from bitmap to ImageTry Again.
141Invalid NFC Tag, unable to read dataPlease try againTry Again.
142Incorrect types for ac record,carrier record and auxiliary record.Please try again.Try Again.
143Reference length indicated longer than available bytes.Please try again.Try Again.
144Tag was lost.Main Error during APDU transmission, tag may be out of field.Try Again.
145ISO-DEP is not supported.Main Tag is not supporting ISO-DEP technology.Try Again.
146Exception when initializing TT4.Error with TT4 configuration.Try Again.
147Wrongly formatted Service Parameter recordPlease try again.Try Again.
148Error with Carrier Configuration record linking.ConnectionHandoverException
with Carrier Configuration record linking.
Try Again.
149Main Initial message is null.Please try again.Try Again.
150NFC Connection TimeoutNFC scanning has timedout.Try Again.
151NFC not supportedNFC not supported on this device.Try Again.
186NFC Session cancelled by userNFC Reader Session invalidated by userTry Again.
187NFC Capability is not added.Session invalidated unexpectedly. Please add NFC capability.Try Again.
201Unable to initialize BLEError in initializing BLE feature of thisThe Mobile ID reader is not able to get BLE. The Mobile ID credential reader may abort the transaction.
202Device Doesn't Support BLEThis device doesn't support the BLE feature.The Mobile ID reader is not able to get BLE. The Mobile ID reader may abort the transaction.
203BLE Scanning ErrorScanning of the BLE devices failed.The Mobile ID reader is not able to scan the BLE devices. The Mobile ID reader may abort the transaction.
204Bluetooth is OFFThis device's Bluetooth is off.The Bluetooth of the device is not enabled. The Mobile ID credential reader may abort the transaction.
205BLE Scanning ErrorPlease provide the BLUETOOTH permissions.
206BLE Connection TimeoutUnable to create BLE communication channel with the Mobile ID device.BLE connection failure. The Mobile ID reader may abort the transaction.
209BLE L2CAP Read ErrorBLE L2CAP connection error while reading.
210BLE L2CAP Write ErrorBLE L2CAP connection error while writing.
211BLE L2CAP Channel Creation ErrorL2CAP channel creation error, Using fallback.
301Transaction CancelledThe transaction has been cancelled by the end-user.Unable to scan the QR code.
302Device DisconnectedUnfortunately device has disconnected. Maybe the device is not in the range of BLE.The Mobile ID credential reader may abort the transaction.
303Timed Out, Please try againBLE connection failure. The Mobile ID credential reader may abort the transaction.
304Request Incomplete.Please select one or more attributes to be included in the request to the Mobile ID credential.The Mobile ID credential reader may inspect the request, ensure request is complete, and resend. The Mobile ID credential reader may abort the transaction.
305Incomplete RequestAn Mobile ID comes to an end of data when expecting more data. For example, an Mobile ID expects certain length, number of arrays elements, or map entries but instead encounters the end of the data. The Mobile ID does not return any data but the error message.The Mobile ID credential reader may inspect the request, ensure request is complete, and resend. The Mobile ID credential reader may abort the transaction.
306Request RejectedThe Mobile ID App indicates that the request is rejected.The Mobile ID credential reader may inspect the problem. The Mobile ID credential reader may continue the transaction.
307Mobile ID Reader Authentication FailedThe Mobile ID indicates there is an error with Mobile ID Reader authenticationThe Mobile ID credential reader may inspect the problem. The Mobile ID credential reader may continue the transaction.
308General ErrorThe Mobile ID App returns an error without any given reason.The Mobile ID credential reader may inspect the request, ensure request is complete, and resend. The Mobile ID credential reader may abort the transaction.
309Invalid RequestRequest can't contain more than 2 age_over_nn as request attributes.
310Error in Reader AuthenticationReaderAuthSign Signature or Certificate cannot be null or empty.
401Parsing ErrorA Mobile ID credential request encountered a data element that is not well-formed (e.g., invalid initial byte) and failed decoding data. The Mobile ID App does not return any data but the error message.The Mobile ID credential reader may inspect the request, ensure request is complete, and resend. The Mobile ID credential reader may abort the transaction.
402Invalid FormatThe Mobile ID App cannot process the requested data element due to a formatting error.
403Data Not FoundThe requested NameSpace or data element within a NameSpace is not found.
404Data Request DeniedThe release of requested data element was rejected by the Mobile ID credential holder.
405Data Not ReturnedThe Mobile ID App does not provide the requested data element without any given reason.
406CBOR decoding errorThe mdoc indicates an error during CBOR decoding that the data received is not valid CBOR.. Returning this status code is optional.
407CBOR validation errorThe mdoc indicates an error during CBOR validation, e.g. wrong CBOR structures. Returning this status code is optional.
451Certificate Path ErrorEither Path is invalid or inaccessible or not a folder path or folder is empty.

Test samples 

QR + BLE sample 

The following screen shows a scan of QR code in the IDEMIA Mobile ID App.

Note: This is for device engagement QR code testing. The full QR code + BLE scenario will only work with a real device using the IDEMIA Mobile ID App.