Developer's Guide for iOS
The IDEMIA Verify SDK - iOS v1.4.0 is intended for developers who want to verify mobile driver's licenses (mDL) within their mobile apps. This guide outlines the necessary steps to configure and use a minimum viable project to verify a mDL.
Prerequisites
Skills required
The integration tasks requires developers with knowledge of:
- iOS frameworks built in Xcode 11.0 or higher
- Swift 5.0 or higher
- macOS 10.14 or higher
External libraries required
- SwCrypt - pod 'SwCrypt'
- SwiftCBOR - pod 'SwiftCBOR'
- DLParser - pod 'DLParser', '~> 3.0'
For optical inspection
- Add BiometricSDK.framework
- Add BiometricSDKAlgorithmPlugin_F5_4_LOW75.framework
- pod 'IDZSwiftCommonCrypto', '~> 0.13.0', => true
- pod 'SwiftBytes', '~> 0.6.0'
- pod "OpenSSL-Universal", => 'https://github.com/krzyzanowskim/OpenSSL.git', => 'master'
For line code
Download the Verify framework from the mi-artifactory: https://mi-artifactory.otlabs.fr/artifactory/verify-sdk-ios-release/com/idemia/idverify/ios/.
- Add LineCodeVerify.framework
For the Line Code SDK integration, please refer to the Line Code SDK Documentation.
Resources required
The tools required for integration on a Macintosh are:
- Xcode 11.0 or above
- iOS SDK tools: release 11 or above (preferably latest version)
- Physical iOS device (simulator is not supported)
SDK implementation
The required permissions in the app info.plist
file are:
- Privacy - Bluetooth Always Usage Description
- Privacy - Bluetooth Peripheral Usage Description
- Privacy - Camera Usage Description
Design considerations
User permissions
Your iOS app must handle user permissions to protect the resources on the target mobile device. Specifically, check 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 permission are required:
-
Camera permission: for the QR code scan
-
Bluetooth permission: for BLE data transfer
How to create your own app
To create your own app, follow the steps below.
-
Add the
Verify.framework
file to your project by pasting the following file in folder at path:/verify-ios-tester-app/src/xcode/VerifyTesterApp/VerifyTesterApp/Frameworks/Verify.framework
. -
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/
-
Link
Verify.framework
to your project by dragging and dropping on Project Settings (General > Frameworks, Libraries, and Embedded Content).
Add pods
- pod 'DLParser', '~> 3.0'
- pod 'SwCrypt'
- pod 'SwiftCBOR'
- pod 'PPpdf417', '~> 7.2.0'
For optical inspection
- Add BiometricSDK.framework
- Add BiometricSDKAlgorithmPlugin_F5_4_LOW75.framework
- pod 'IDZSwiftCommonCrypto', '~> 0.13.0', => true
- pod 'SwiftBytes', '~> 0.6.0'
- pod 'OpenSSL-Universal'
For line code
- Add LineCodeVerify.framework
For the IDEMIA Line Code SDK - iOS integration, please refer to the Line Code SDK Documentation.
-
Call
IDVerifyTerminal.getClient
and initialize theIDVerifyTerminal
shared object in theAppDelegate.swift
file.Swift1//Only for Optical Inspection2let license = BioSDKLicense(lkmsURL:serverEndpointUrl, lkmsProfileId: profileID, lkmsApiKey: apiKey)Note:
- Minimum threshold for the BioTemplate authentication score (Optical Inspection use case) is 3500 by default.
- Internet connection is required for 1st time transaction of Optical Inspection for attributes retrieval. The Mobile ID credential is downloaded from server only once and will not be downloaded again until either expired or app is reinstalled/data cleared.
- By default no logs shall be visible on logcat from the SDK. Use enableDebug(true) for debugging purpose only if needed and toggle it to false for production release.
Swift1let config = Configs.Builder()2 .enableDebug(isDebuggable: isDebuggable)3 .setBioSDKLicense(bioSDKLicense: license) //Optional: required only if you're to use Optical Inspection4 .build()56sharedVSDKClient = IDVerifyTerminal.getClient(configs: config)
Obtain a LKMS license
Please contact our support team to get an LKMS license for your app. You can skip this step if your app doesn't intend to use "Optical Inspection" feature of the IDEMIA Mobile ID Verify App.
-
Scan the QR or PDF417 codes.
Swift1/**2 * Response callback for parse engagement QR code data or PDF417 raw data from physical or **Mobile ID** credential holder3 */4 //MARK: parsed QRCode5 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)910 }11 }1213 //MARK: parsed 2DBarCode14 func parsedDataFor2DBarCode(trimmedQRCode: String){15 DispatchQueue.global(qos: .default).asyncAfter(deadline: .now() + 0.2) {16 let config = self.formAndReturnAppConfigsParamForAPI(qrString: trimmedQRCode)17 sharedVSDKClient?.parsePDF417(apiConfig: config, responseCallback: self)18 }19 }2021 // Returns ApiConfigs with all the parameters22 func formAndReturnAppConfigsParamForAPI(qrString qr: String?) -> ApiConfigs? {23 guard let tempQRString = qr else {24 return nil25 }26 // Build app configs27 let apiConfigs = ApiConfigs.ConfigBuilder()28 .withData(inputData:tempQRString)29 .setAgeOverNN(age: pickedAge)30 .build()31 return apiConfigs32 } -
Handle the response result after scanning the QR code or 2D barcode. After scanning the QR code successfully, you will get the result in
onSuccess
.Swift1func onSuccess(response: Any?){2 }3 func onError(error: VerifyError){45 } -
Send a request to the Mobile ID App to get the license details.
The
sendRequest()
method will return the response from the 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.Swift1// Set 'appConfig' as follows if you want to use all attributes as optional parameters2var dataItems = getMandatoryParams()3dataItems.append(contentsOf: getOptionalParams())45let apiConfigs = AppConfigs.MIDRequestBuilder()6 .addParam(listParams: dataItems)7 .build()Swift1// Set 'appConfig' as follows if you want to use only the suggested attributes as optional parameters2var dataItems = getOptionalParams() let apiConfigs =3AppConfigs.MIDRequestBuilder() .addParam(listParams: paramsList, useDefaults:4true) .build()Swift1//Send the request by using `appConfig` which you set earlier2sharedVSDKClient?.sendRequest(apiConfig: apiConfigs, responseCallback: self)3}Swift1// send request using new namespace and paramList support23func sendrequest(){45 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))1314 namespaceParamList[MIDParamConstants.DOCTYPE_ORG_AAMVA_US] = aamvaParamsList15 namespaceParamList[MIDParamConstants.NAMESPACE_18013_5 ] = isoParamsList1617 let apiConfigs = ApiConfigs.MIDRequestBuilder()18 .version(version: MIDParamConstants.REQUEST_VERSION)19 .addDocType(docType: "my.cusom.docType.custom1") //example docType12021 //1. add22 .addParams(namespaceParamList)23 // add again to test if duplicates are removed24 .addParams(MIDParamConstants.NAMESPACE_18013_5,isoParamsList)25 //2. add more params one by one with custom namespce26 .addParam(MIDParamConstants.NAMESPACE_18013_5,MIDRequestParam(paramName: "custom_param1"))27 .addParam("my.custom.namespace",MIDRequestParam(paramName: "custom_param1"))2829 .addParam("my.custom.namespace",MIDRequestParam(paramName: "custom_param2"))30 .addParam("my.custom.namespace",MIDRequestParam(paramName: "custom_param3"))31 //duplicates will be removed32 .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 this35 .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") ]//duplicate40 )4142 .buildDoc() //build doctype143 .addDocType(docType: "my.cusom.docType.custom2") //example docType244 .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") ]//duplicate49 )50 .buildDoc() //build doctype25152 .build()5354 //call sendRequest API55 sharedVSDKClient?.sendRequest(apiConfig: apiConfigs, responseCallback: self)56 // 3. Read request params supplied from app and make the request structure accordingly.5758} -
Callback for the
sendRequest
IDEMIA Verify SDK - iOS API to receive and display the response data from the Mobile ID App.Swift1/**2 * Request callback for the `sendRequest` SDK API to receive and display the response data from the mDL.3 */45 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 } -
You can cancel the transaction at any time by calling the
cancelRequest()
method.Swift1sharedVSDKClient?.cancelRequest(responseCallback: self,cancellationReason: .CANCELED_BY_USER) -
Get the SDK version by calling it directly with class name.
Swift1IDVerifyTerminal.version
Updates and additions
- Added optional method
withImage
added inApiConfigs.ConfigBuilder
forinitDeviceEngagement
which takes the captured device screenshot image (while scanning the compact QR code) for BioTemplate authentication - Added optional method
setBioSDKLicense
is added inConfigs.Builder
to supply the LKMS license detail to the IDEMIA Verify SDK - iOS. - Added model class
OIDLDataModel
, which encapsulates the attributes list and corresponding security checks for the Optical Inspection QR code result - Added the new model class
OpticalInspectionAuth
to return security checks related to Optical Inspection.
Request parameters
Item# | Identifier | Param Name | CBOR Type |
---|---|---|---|
1 | ADMINISTRATIVE_NUMBER | administrative_number | Major type 3 |
2 | GENDER | gender | Major type 3 |
3 | HEIGHT | height | Major type 0 |
4 | WEIGHT | weight | Major type 0 |
5 | EYE_COLOR | eye_color | Major type 3 |
6 | HAIR_COLOR | hair_color | Major type |
7 | BIRTH_PLACE | birthplace | Major type 3 |
8 | RESIDENT_ADDRESS | resident_address | Major type 3 |
9 | PORTRAIT_CAPTURE_DATE | portrait_capture_date | Tag value 0 of major type 6 |
10 | AGE_IN_YEARS | age_in_years | Major type 0 |
11 | AGE_BIRTH_YEAR | age_birth_year | Major type 0 |
12 | AGE_OVER_NN | age_over_NN | Value 20/21 of major type 7 |
13 | ISSUING_JURISDICTION | issuing_jurisdiction | Major Type 3 |
14 | NATIONALITY | nationality | Major type 3 |
15 | RESIDENT_CITY | resident_city | Major type 3 |
16 | RESIDENT_STATE | resident_state | Major type 3 |
17 | RESIDENT_POSTAL_CODE | resident_postal_code | Major type 3 |
18 | BIOMETRIC_TEMPLATE_XX | biometric_template_xx | Major type 2 |
19 | NAME_NAT_CHAR | name_nat_char | Major type 3 |
20 | MGMT_NEXT_UPDATE | mgmt_nextupdate | Tag value 0 of major type 6 |
21 | FAMILY_NAME | family_name | Major type 3 |
22 | GIVEN_NAME | given_name | Tag value 0 of major type 6 |
23 | BIRTHDATE | birthdate | Tag value 0 of major type 6 |
24 | ISSUE_DATE | issue_date | Tag value 0 of major type 6 |
25 | EXPIRY_DATE | expiry_date | Major type 3 |
26 | ISSUING_COUNTRY | issuing_country | Major type 3 |
27 | ISSUING_AUTHORITY | issuing_authority | Major type 3 |
28 | DOCUMENT_NUMBER | document_number | Major type 3 |
29 | PORTRAIT | portrait | Major type 2 |
30 | MGMT_LAST_UPDATE | mgmt_lastupdate | Tag value 0 of major type 6 |
31 | MGMT_VALIDITY | mgmt_validity | Tag value 0 of major type 6 |
32 | ONLINE_TOKEN_XXXX | online_token_xxxx | Major type 3 |
34 | DRIVING_PRIVILEGES | driving_privileges | Major type 4 |
35 | REAL_ID | RealID | Major type 3 //org.aamva namespace |
36 | SIGNATURE_USUAL_MARK | signature_usual_mark | Major type 3 |
37 | ONLINE_URL_XXXX | online_url_xxxx | Major type 3 |
38 | BIRTHDATE | birth_date | Major type 3 |
39 | BIRTH_PLACE | birth_place | Major type 3 |
40 | NAME_NAT_CHAR | name_national_character | Major type 3 |
Expected results
Data Fields | Data type/Unit | Sample Value | Action Required |
---|---|---|---|
administrative_number | Text/String | "1234453" | |
gender | Text/String | "M" | |
height | Integer/Centimeter | "157" | |
weight | Integer/Kg | "56" | |
eye_color | Text/String | "BLU" | |
hair_color | Text/String | "BLACK" | |
birthplace | Text/String | "NY" | |
resident_address | Text/String | "123, ABC Street" | |
portrait_capture_date | DateTime/RFC3339 | "1985-04-12T23:20:50Z" | |
age_in_years | Integer/String | "34" | |
age_birth_year | Integer/String | "1978" | |
age_over_NN | Boolean/String | "true" | |
issuing_jurisdiction | Text/String | "NY" | |
nationality | Text/String | "US" | |
resident_city | Text/String | "NY" | |
resident_state | Text/String | "NY" | |
resident_postal_code | Text/String | "58773" | |
name_nat_char | Text/String | "US" | |
mgmt_nextupdate | DateTime/RFC3339 | "1985-04-12T23:20:50Z" | |
family_name | Text/String | "Sample" | |
given_name | Text/String | "Joe" | |
birthdate | DateTime/RFC3339 | "1985-04-12T23:20:50Z" | |
issue_date | DateTime/RFC3339 | "1985-04-12T23:20:50Z" | |
expiry_date | DateTime/RFC3339 | "1985-04-12T23:20:50Z" | |
issuing_country | Text/String | "US" | |
issuing_authority | Text/String | "NY" | |
document_number | Int/String | "782593823" | |
portrait | ByteArray/Bytes | ||
mgmt_lastupdate | DateTime/RFC3339 | "1985-04-12T23:20:50Z" | |
mgmt_validity | DateTime/RFC3339 | "1985-04-12T23:20:50Z" | |
driving_privileges | Text/String | "C" | |
RealID | Boolean/String | true | |
signature_usual_mark | ByteArray/Bytes | ||
birth_date | DateTime/RFC3339 | "1985-04-12T23:20:50Z" | |
birth_place | Text/String | "NY" | |
name_national_character | Text/String | "US" |
Expected results (PDF417 scan)
Data Fields | Data type/Unit | Sample Value |
---|---|---|
gender | Text/String | "M" |
height | Integer/inches | "71" |
eye_color | Text/String | "BLU" |
resident_address | Text/String | "123, ABC Street" |
age_in_years | Integer/String | "34" |
age_over_NN | Boolean/String | "true" |
resident_city | Text/String | "NY" |
resident_state | Text/String | "NY" |
resident_postal_code | Text/String | "58773" |
family_name | Text/String | "Sample" |
birthdate | DateTime/RFC3339 | "1985-04-12T23:20:50Z" |
issue_date | DateTime/RFC3339 | "1985-04-12T23:20:50Z" |
expiry_date | DateTime/RFC3339 | "1985-04-12T23:20:50Z" |
issuing_country | Text/String | "USA" |
document_number | Int/String | "782593823" |
driving_privileges | Text/String | "C" |
Expected results (Optical Inspection)
Data Fields | Data type/Unit | Sample Value |
---|---|---|
gender | Text/String | "M" |
family_name | Text/String | "Sample" |
given_name | Text/String | "Joe" |
birthdate | DateTime/RFC3339 | "1985-04-12T23:20:50Z" |
expiry_date | DateTime/RFC3339 | "1985-04-12T23:20:50Z" |
Error codes
Error Code | Error Code Message | Description | Action Required |
---|---|---|---|
101 | Invalid QR Code | Please try again. | Unable to scan the QR code. |
102 | QR Data item is missing or found any issue | This is a QR data issue. | Unable to find some elements in the QR data item. The Mobile ID reader may abort the transaction. |
103 | QR Code parsing error | Unable to parse Mobile ID QR code. | Unable to parse the QR code that the Mobile ID App has provided. |
104 | QR code scan error | Unable to Scan QR code may be because of invalid data or bad encoding. | Unable to scan the QR code. |
108 | License Validation for Optical Inspection Failed | Please try again with the correct credentials/ stable internet connection. | Try Again. |
109 | License expired | Please contact support to renew the license | |
201 | Unable to initialize BLE | Error in initializing BLE feature of this | The Mobile ID reader is not able to get BLE. The Mobile ID credential reader may abort the transaction. |
202 | Device Doesn't Support BLE | This 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. |
203 | BLE Scanning Error | Scanning 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. |
204 | Bluetooth is OFF | This device's Bluetooth is off. | The Bluetooth of the device is not enabled. The Mobile ID credential reader may abort the transaction. |
205 | BLE Scanning Error | Please provide the BLUETOOTH permissions | |
206 | BLE Scanning Error | Please enable Bluetooth to get scan results | |
207 | BLE Scanning Error | Your device does not support BLE | |
208 | BLE Connection Timeout | Unable to create BLE communication channel with the Mobile ID device. | BLE connection failure. The Mobile ID reader may abort the transaction. |
301 | Connection Lost | Error occurred while transferring the data. | The Mobile ID reader is not able to maintain the connection with the device. The Mobile ID reader may abort the transaction. |
302 | Error Creating Request | Unable to create the request for the Mobile ID credential. | The Mobile ID credential reader is not able to create the request. The Mobile ID credential reader may abort the transaction. |
303 | Transaction Cancelled | The transaction has been cancelled by the user. | Unable to scan the QR code. |
304 | Connection Failed | Unable to connect the device. | There is a BLE connection failure. The Mobile ID credential reader may abort the transaction. |
305 | Device Disconnected | Unfortunately device has disconnected. Maybe the device is not in the range of BLE. | The Mobile ID credential reader may abort the transaction. |
306 | Timed Out, Please try again | BLE connection failure. The Mobile ID credential reader may abort the transaction. | |
307 | Request 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. |
308 | Incomplete Request | Please select one or more attributes to be included in the request from 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. |
309 | Mobile ID credential Reader Authentication Failed | The optional Mobile ID credential reader authentication is present but the Mobile ID App fails to authenticate the Mobile ID credential reader. The Mobile ID App returns the error message and may include data as well. | The Mobile ID credential reader may inspect the problem. The Mobile ID credential reader may continue the transaction. |
310 | Request Rejected | The 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. |
311 | General Error | The 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. |
401 | Parsing Error | A 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. |
402 | Invalid Format | The Mobile ID App cannot process the requested data element due to a formatting error. | |
403 | Data Not Found | The requested NameSpace or data element within a NameSpace is not found. | |
404 | Data Request Denied | The release of requested data element was rejected by the Mobile ID credential holder. | |
405 | Data Not Returned | The Mobile ID App does not provide the requested data element without any given reason. |
Test samples
Line code sample
Optical inspection sample
PDF417 sample
QR + BLE sample
Note: The below screenshot is only for device engagement QR code testing. The full QR code + BLE scenario will only work with real device with the IDEMIA Mobile ID App.