SDK for Android
Introduction
The IDEMIA Verify SDK for Android 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 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. You 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 should be done by developers with knowledge of:
- Android Studio
- Java/Kotlin for Android
- Android SDK
- Android operating system
Resources Required
Integrations may be performed on PC Windows, Linux, or Macintosh.
- Android Studio Flamingo 2022.2.1 or above
- Android SDK tools: preferred latest version (release 31 or above)
- JDK: preferred latest version (8 or above)
- Android device (emulator is not supported)
- Minimum SDK version is 30 (Android 11)
Other Requirements
Tech Stack | Description |
---|---|
Development environment | Android Studio Flamingo 2022.2.1+, Windows, Mac or Linux, JDK 8.. JDK17 |
Programming language | Kotlin, Java |
Kotlin Version | 1.8.20 |
Minimum supported OS Version | Android 11.0 (API 30) |
Target SDK version | Android 13.0 (API 33) |
Components
The SDK is made up of the following components:
IDVerifyTerminal
acts as the entry point for initializing device engagement. It sends the request to the Mobile ID credential holder, receives the response, and sends the parsed model back to the calling app. It exposes the following APIs to the caller/client with the help of the concrete classIDVerifyClient
.
SDK Core APIs
- version
Kotlin1//Use IDVerifyTerminal.version to read Verify SDK version. e.g.2Log.d(TAG, "SDK Version=${IDVerifyTerminal.version}")
- getClient
Kotlin1/**2 * Create and return verify SDK V1 client using this function.3 *4 * @param configs configurations for verify sdk to initialize5 * @param actContext; activity context from app.. We have allowed to pass as Context instead of6 * Activity explicitly because some features can even work with app context however for features7 * like NFC, WifiAware it strictly require Activity context; therefore it is recommended to8 * use Activity context when creating SDK client from your app.. It is also recommended that9 * your app maintain a singleton object of SDK to avoid any concurrency issues.10 *11 * @return `IDVerifyClient` object as IDVerifyTerminal12 */13fun getClient(configs: VSDKConfigs,actContext:Context): IDVerifyTerminal
- getClientV2
Kotlin1/**2 * Create and return verify SDK V2 client using this function..3 *4 * @param configs configurations for verify sdk to initialize5 * @param actContext; activity context from app.. We have allowed to pass as Context instead of6 * Activity explicitly because some features can even work with app context however for features7 * like NFC, WifiAware it strictly require Activity context; therefore it is recommended to8 * use Activity context when creating SDK client from your app.. It is also recommended that9 * your app maintain a singleton object of SDK to avoid any concurrency issues.10 *11 * @return `IDVerifyClientV2` object to access the v2 APIs..12 */13fun getClientV2(configs: VSDKConfigs, actContext:Context): IDVerifyClientV2
- loadCertificates
Kotlin1/**2 * Load certificates from a given location from device storage path3 * @param vical file path from device storage if accessible directly.4 * defaults to null if not supplied and fallback to load vical from assets/vical folder if available5 * @param callback async callback to return success or error6 */78fun loadCertificates(path: String?=null,callback: SuccessCallback<Int>?)
- initDeviceEngagement
Kotlin1/**2 * perform device engagement using QR code / NFC3 * @param apiConfigs apiConfigs to configure QR code/NFC flow etc.4 * Uses:5val apiConfigs = ApiConfigs.Builder()6.withData(scannedData) // for qr code device engagement7//OR .withConfigs().useNfcHandover().buildConfigs() //for nfc device engagement8.build()910 * @param deviceEngagementCallback callback to return the DeviceEngagement model11 * and/or other events during engagement.12 * Usage:13<p>14sdkClintV2.initDeviceEngagement(apiConfigs,object:DeviceEngagementCallback(){15//override the interface methods here16})17</p>18 */19fun initDeviceEngagement(apiConfigs: ApiConfigs?, callback: DeviceEngagementCallback<in ResponseItem?>)
- prepareConnection
Kotlin1/**2 * Initialize and setup connection components as per`ConnectionConfigs` configurations supplied.3 * This API is available in `IDVerifyClientV2` only and must be called explicitly if SDK client4 * is created using `IDVerifyTerminal.getClientV2`.5 */67fun prepareConnection(apiConfigs: ConnectionConfigs, callback: PrepareConnectionCallback?)
- sendRequest
Kotlin1/**2 * send request to Mobile ID based on the use case selected by user in Verify application3 * @param apiConfigs: configurations and optional Mobile ID request params4 * @param callback: callback to send progress and response data back to app5 *6 * 1. create Mobile ID request based on supplied Use Case or parameters/configs7 * 2. onCreate communication channel (BLE/NFC/wifiAware ...) as per engagement data8 * 3. send request to Mobile ID on communication channel9 */10fun sendRequest(apiConfigs: ApiConfigs? = ApiConfigs.Builder().build(),11 callback: ICallback<in ResponseItem?, in ProgressItem>)
- cancelRequest
Kotlin1/**2 * cancel any transaction/running session with Mobile ID. overload to default cancellation3 * return true if transaction is cancelled successfully4 */5fun cancelRequest(): Boolean
- terminateConnection
Kotlin1/**2 * Terminate the current connection to let user call prepareConnection again. this API is available3 * in IDVerifyClientV2 only.4 */5fun terminateConnection(): Boolean
- terminateSession
Kotlin1/**2 * Terminate/Close the connection, wipe out session data and ready to process next transaction from3 * user. This API is available in IDVerifyClientV2 only and equivalent to `cancelRequest` API of V1.4 */5fun terminateSession(): Boolean
- isRequestOngoing
Kotlin1/**2 * Check whether a transaction is already setup and in-progress state. Integrator can use this3 * api to check a running transaction and cancel (if needed using `cancelRequest`) before4 * starting a fresh transaction.5 * Normally this api may not be used because once the transaction is complete verify SDK will return6 * to initial state, however in case of some negative test cases it may be useful to check before7 * starting a new transaction.8 */9fun isRequestOngoing(): Boolean
User Permissions
When designing your app, you need to consider that your Android app must handle end-user permissions to protect the resources on the target mobile device. You have to verify that the end-user grant the following permissions to the app:
- Camera permission (for QR code scanning using Camera)
- Location permission (when BLE client mode and WiFiAware use cases)
- Nearby devices permission required for WiFiAware use case (android 13 and above)
The end-user must grant access when using an Android version higher than 2.3 (Android 6.0 Marshmallow). The SDK will throw an exception or error, if the required permissions are not granted.
Sample Project
Download the IDEMIA Verify Sample App – Android using below URL:
Create Your Own App
Follow the steps mentioned below to Integrate the VerifySDK in your App:
Step 1: Add the Verify Library dependencies in your Android project
To create your own app, you must add the VerifySDK libraries to your project. There are two ways of doing this:
Option A: Import VerifySDK from mi-artifactory
** Import VerifySDK from mi-artifactory**
- Add the following configs in gradle.properties as shown in the snippet:
Groovy1artifactory_remoteUrl=https://mi-artifactory.otlabs.fr/artifactory/verify-sdk-release2artifactory_username=<username>3artifactory_password=<password>
- Add the following dependency in your project/build.gradle as shown in the snippet:
Groovy1buildscript {23 repositories {4 google()5 jcenter()6 maven {7 url "https://plugins.gradle.org/m2/"8 }9 //required below maven block to sync verify SDK artifact from mi-artifactory10 maven {11 url "${artifactory_remoteUrl}"12 credentials {13 username = "${artifactory_username}"14 password = "${artifactory_password}"15 }16 }1718 }19 ...20 }21 ...2223 allprojects {24 repositories {25 ...26 maven { url 'https://github.com/c-rack/cbor-java' }27 maven {28 url "${artifactory_remoteUrl}"29 credentials {30 username = "${artifactory_username}"31 password = "${artifactory_password}"32 }33 }3435 }36 project.ext{37 sdkVersionName='4.1.0'38 sdkVersionCode=xxxx //use latest release version number for v4.1.0 from mi-artifactory3940 }4142 }
- Add following dependency in app/build.gradle as shown in the snippet:
Groovy1dependencies {2 implementation("com.idemia.android:idverify:${project.ext.sdkVersionName}-${project.ext.sdkVersionCode}@aar") {3 transitive = true4 }5 ...6}
- If you have been using Option B and now moving to Option A, then you may need to delete the previous .aar file from your app/libs directory
**Option B: Import VerifySDK as .aar file **
Below steps 1-4 are only applicable if you intend to integrating verify using physical .aar file by copying it to your app/libs/ directory. (Note: this is not a recommended method due to additional steps involved and may cause runtime issues if there is any version mismatch for supporting dependencies)
- Download the latest .aar file from artifactory path:
Language not specified1https://mi-artifactory.otlabs.fr/artifactory/verify-sdk-release/com/idemia/android/idverify/4.1.0-xxxx/
-
Copy idverify-4.1.0-
.aar into your project app/libs directory -
Add below line in app/build.gradle
Groovy1dependencies {2 implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')3 ...4 } -
Include the supporting dependencies in app/build.gradle in your Reader App to work, as shown in the snippet:
Groovy1dependencies {2 //additional dependencies required for idemia id.verify sdk3 implementation "co.nstant.in:cbor:0.9"4 implementation "org.bouncycastle:bcprov-jdk15to18:1.76"5 implementation("org.bouncycastle:bcpkix-jdk15to18:1.76")6 implementation "com.google.code.gson:gson:2.8.9"7 }
Additional Steps to Compile and Build your Android project
Following steps are common for both Option A or Option B.
- Add the required permissions to the project:
XML1<!-- required camera for QR code scanning-->2 <uses-permission android:name="android.permission.CAMERA"/>3 <uses-feature android:name="android.hardware.camera.any" />4 <!-- Request legacy Bluetooth permissions on older devices. -->5 <!-- required for BLE data transfer-->6 <uses-permission android:name="android.permission.BLUETOOTH"7 android:maxSdkVersion="30"/>8 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"9 android:maxSdkVersion="30"/>10 <!--BLE permissions for Android 12-->11 <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />1213 <!-- Needed only if your app makes the device discoverable to Bluetooth14 devices. -->15 <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />1617 <!-- Needed only if your app communicates with already-paired Bluetooth18 devices. -->19 <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />2021 <!-- required for wifiaware and BLE scanning -->22 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />23 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />24 <!--Required for online use cases -->25 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />26 <uses-permission android:name="android.permission.INTERNET" />27 <!-- required for wifiaware data transfer-->28 <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />29 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>30 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>31 <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" android:usesPermissionFlags="neverForLocation"/>32 <!-- required for nfc data transfer-->33 <uses-permission android:name="android.permission.NFC"/>
- In order to allow your app to install in devices which do not support a certain feature, below lines can be added just below the permissions:
XML1<!-- Do not install in devices which do not have Camera -->2 <uses-feature android:name="android.hardware.camera" android:required="true"/>3 <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>4 <!-- allow app to install in devices which do not have NFC support so that5 they can still use other features e.g QR code and WifiAware use-cases -->6 <uses-feature android:name="android.hardware.nfc" android:required="false"/>7 <!-- allow app to install in devices which do not have wifiAware support so that8 they can still use other features e.g QR code and NFC use-cases -->9 <uses-feature android:name="android.hardware.wifi.aware" android:required="false"/>
Note: It is not recommended to have all three configs with
required="false"
. Normally if all three use cases (QR Code, NFC handover/transfer, WifiAware Transfer) are supported in your app then you may want to let users install your app regardless of their device supports or not NFC and/or WifiAware; for that you can addrequired="false"
for WifiAware and NFC andrequired="true"
for Camera.
- Gradle Sync and build!
Step 2: Integrate QR Code + BLE/NFC/WiFi Use case
-
Initialize the VerifySDK configurations by calling
VSDKConfigs.Builder().build()
in your activity/fragment. -
Create the VerifySDK client object to call the SDK APIs as shown in the snippet:
Kotlin1val config = VSDKConfigs.Builder().build()2 mSdkClient = IDVerifyTerminal.getClientV2(config,actContext)3// OR mSdkClient = IDVerifyTerminal.getClient(config,actContext) //call `getClient` to use legacy client
Notes:
- IDVerifyTerminal.getClientV2() is recommended for new integrators for better control over SDK APIs.
- Use
DebugCallback
withenableDebug
to get the logs via a callback and save them in the file, as shown in the snippet:
Kotlin1val config = VSDKConfigs.Builder(this)2 .enableDebug(LogLevel.DEBUG,debugCallback = object:DebugCallback{3 override fun didReceiveLogs(logs: DLog) {4 //save or print logs here5 }6 })7 ...8 .build()
Note: The above is useful in scenarios when logcat strips some logs because they are too big, for example, if response HEX with end-user image becomes too big to print in logcat.
- Enabling debug verbose logs in the production app may adversely affect the transaction speed and overall performance of the Verify SDK for Android.
- It is recommended that integrator should use the LogLevel properties carefully to configure limited logs in production flavour.
- Default LogLevel will be NONE if
enableDebug
is not configured with at least one LogLevel - If you want full debug logs except PIIs then use DEBUG_NO_PII
- DEBUG and VERBOSE may include PIIs hence should be avoided in production release
- Supported LogLevel are:
Language not specified1TRANSACTION_TIME : Only transaction time event logs shall be printed on console and returned to`debugCallback.didReceiveLogs()`2 These logs shall be persisted in runtime memory during the transaction and shall be dumped3 to console in a time sorted order (FIFO) once the transaction concludes.45 TROUBLESHOOTING : Only minimal troubleshooting logs (e.g. exceptions and errors) shall be printed on console and6 returned to `debugCallback.didReceiveLogs()`.7 These logs would be helpful to troubleshoot the failures cases during transactions.89 DEBUG : All debug logs include PIIs are returned or printed in console1011 DEBUG_NO_PII : All except PII logs shall be returned to `debugCallback.didReceiveLogs()` LogLevel.DEBUG_NO_PII has highest priority12 if multiple logLevel values are configured via `enableDebug` vararg param. (excluding LogLevel.NONE- in case of NONE is found,13 all other configs shall be ignored and all logs shall be disabled)1415 VERBOSE : Allow all logs (transaction_time, troubleshooting, and Debug) including PIIs1617 NONE : No logs shall be printed. LogLevel.NONE has highest priority if multiple18 logLevel values are configured via `enableDebug` vararg param
2.1. Call loadCertificates()
api to load IACA certificates from given path. This step is necessary for a successful transaction since
Verify SDK will validate the mDL response against the certificates from supplied path.
Kotlin1mSdkClient?.loadCertificates(path=<directory_path/vical>,object : SuccessCallback<Int> {2 override fun onSuccess(response: Int?) {3 Log.d("HomeFragment","*Certificate Loading, loaded cert count:$response")45 }6 override fun onError(error: IError?) {7 Log.d("HomeFragment","*Certificate Loading error: ${error?.errorCode}")8 }9 })
How to create directory structure for hosting vical files for your Reader app?
- Copy download vical files at some app private location which should be accecisble at runtime
- Create new directory vical/ inside assets and copy iaca files for each environment as per below structure.
- assets/vical
- Dev
- iaca.vical
- iaca.vical.pem
- UAT
- iaca.vical
- iaca.vical.pem
- PROD
- iaca.vical
- iaca.vical.pem
- Dev
Note:
- The vical file and corresponding IACA file to validate vical coseSign1 should be named exactly as in above sample
- For example, if vical file name is "myiaca.vical" then IACA should be named "myiaca.vical.pem"
How To configure vical from app/assets directory?
- Create 'assets/vical' folder inside app/main or app/flavorName/
- Copy iaca and corresponding IACA cert per environment similar to structure defined above.
- Set value for
path
tonull
while callingloadCertificates
api and verifySDK shall fallback to use assets/vical path
Kotlin1.loadCertificates(path=null,callback=object :SuccessCallback<Int>{2 override fun onSuccess(response: Int?) {3 //Log.d("HomeFragment","*Certificate Loading, loaded cert count:$response")4 }56 override fun onError(error: IError?) {7 //Log.d("HomeFragment","*Certificate Loading error: ${error?.errorCode}")8 }910 })
Note:
loadCertificates()
api should be called only once on application launch when SDK object is created first; no need to be called for each transaction.
- Call the desired SDK API by supplying the necessary
apiConfigs/request
parameters and using callback to receive the results.
Kotlin1* `mSdkClient.initDeviceEngagement(apiConfigs,callback)`2* `mSdkClient.prepareConnection(connectionConfigs,callback)`3* `mSdkClient.sendRequest(apiConfigs,callback)`4* `mSdkClient.terminateConnection()`5* `mSdkClient.terminateSession()`6*
- To scan the QR code follow the below steps to communicate with the Mobile ID App and display the results on the Verify App screen:
- Scan the QR code using Zxing or any other library and then call
initDeviceEngagement
API as shown in the snippet:
Kotlin1fun onQRCodeScanned(scannedData: String?) {2 doHandleScannedData(scannedData)3 }
- Create the response callback for parsing engagement QR code data as shown in the snippet:
Kotlin1open fun doHandleScannedData(scannedData: String?) {2 if (!scannedData.isNullOrEmpty()) {3 val nfcConfigsBuilder=NfcConfigs.Builder()4 val apiConfigs = ApiConfigs.Builder()5 .withData(scannedData)6// //OR useNfcHandover() as below commented section//for nfc device engagement7// .withConfigs().apply {8// useNfcHandover()9// /* use additional configs for nfcHandover if needed10// * verify sdk will use default and best ppossible configs if no configs are11// * set using `setNfcConfigs`12// */13//14// nfcConfigsBuilder.enableReaderEngagement() //use this cofig to enable readerEngagement bytes ON for Nfc negotiated handover15// nfcConfigsBuilder.enableWiFiACRecord(true) //use this to indicate support for WiFiAware16// nfcConfigsBuilder.leRole(LeRole.MDOC_CENTRAL_ONLY) // use this to indicate preferred LE Role17// //... // additional configs to fine tune based on underlying hardware/device/OS if needed18// setNfcConfigs(nfcConfigsBuilder.build())19// }20// .buildConfigs()21 .build()22 mSdkClient?.initDeviceEngagement(apiConfigs, mDEParserCallback)23 } else {24 // QR scan failed! try again25 }26 }27 /** Response callback for parse engagement QR code data */28 private val mDEParserCallback = object : ResponseCallback<DeviceEngagementModel?> {29 override fun onSuccess(deviceEngegmentModel: DeviceEngagementModel?) {30 // deviceEngegmentModel received. perform next step31 doPrepareConnection(deviceEngagementModel)32 // OR for legacy client33 // doStartDataTransfer(deviceEngagementModel)34 }35 override fun onError(error: IError?) {36 handleError(error)37 }38 }
- For V2 client call
prepareConnection
api before calling sendRequest else skip to step 5.1
Kotlin1private fun doPrepareConnection(deModel: DeviceEngagementModel?) {2 val connectionConfigs = ConnectionConfigs.Builder()3 .withConfigs().apply {4 setResponseTimeout(10000) //sdk will disconnect and return with error code 303 if transaction doesn't complete in this time5 setConnectTimeout(10000) //sdk will return with error code 206 is connection not established withing this time6 //enableL2Cap() //to enable BLE l2cap if available and supported78 }.buildConf()9 .build()10 mSdkClient?.prepareConnection(connectionConfigs,11 object : PrepareConnectionCallback {12 override fun onSuccess(response: ConnectionInfo?) {13 when (response?.connectionState) {14 ConnectionState.CONNECTED -> {15 doStartDataTransfer(deModel)16 }17 else -> {18 Log.d("MainActivity","prepareConnection: connectionState=${response?.connectionState}")19 }20 }21 }2223 override fun onError(error: IError?) {24 handleError(error)25 }26 })27 }
5.1. Send the request to the Mobile ID App to get the credential details. The sendRequest()
method will return the response from the user's Mobile ID App. If you've received it successfully, then you can display all the attributes of the Mobile ID App response in your own result activity, as shown in the snippet:
Kotlin1private fun doStartDataTransfer(deModel: DeviceEngagementModel?) {23 val namespaceParamMap = getRequestedParamsMap() // make map of namespace to List<MIDRequestParam>45 val apiConfigs = ApiConfigs.MIDRequestBuilder()6 .version("1.0")7 .withConfigs().apply {8 //verify sdk will disconnect and return with error code 303 if transaction doesn't complete in this time9 setResponseTimeout(20000)10 //verify sdk will return with error code 206 is connection not established withing this time11 setConnectTimeout(10000)12 clearBLECache() // enable BLE cache to clear for every transaction to avoid connection issues13 //for wifiaware data transfer; since v2.4.014 setNANConfigs(NANConfigs.Builder().apply {15 setSubscribeType(DEFAULT_NAN_SUBSCRIBE_TYPE)16 setTtlSec(15)17 }.build())18 }.buildConf()19 //add docType20 .addDocType(DOCTYPE_18013_5).apply {21 // pass all request params as Map<namespace->List<MIDRequestParam>22 addParams(namespaceParamMap)23 //OR use namespace -> param overload to add all params one by one24 addParam("org.aamva.us", MIDRequestParam(REAL_ID))25 addParam("org.aamva.us", MIDRequestParam("<AttributeName>"))26 //OR use another overload to . duplicate params shall be removed if found27 addParams(DEFAULT_NAMESPACE_18013_5_1, namespaceParamMap.get(DEFAULT_NAMESPACE_18013_5_1))28 addParams(NAMESPACE_ORG_ISO_AAMVA, namespaceParamList.get(NAMESPACE_ORG_ISO_AAMVA))29 //OR this way30 addParams(31 "my.custom.namespace2", listOf(32 MIDRequestParam("custom_param_nm21"),33 MIDRequestParam("custom_param_nm22"),34 MIDRequestParam("custom_param_nm23"),35 MIDRequestParam("custom_param_nm21") //duplicate36 )37 )38 //OR use 3rd overload to pass params one by one39 .addParam("my.custom.namespace", MIDRequestParam("custom_param1"))40 // add requestInfo as map41 .addRequestInfo(42 infoMap = hashMapOf(43 "reqKey1" to "reqVal1",44 "reqKey2" to "reqVal2",45 "reqKey3" to false,46 "reqKey4" to 333447 )48 )49 //or use other overload to add one by one50 .addRequestInfo("reqinfo1", "value1")51 .addRequestInfo("reqinfo2", "value2")52 .addRequestInfo("reqinfoLong", 180L)53 .addRequestInfo("reqinfoBool", true)54 .addRequestInfo("reqinfoBytArr", "sdkghdkgs".toByteArray())55 .addRequestInfo("reqinfoDouble", 3.7)56 .addRequestInfo("reqinfoFloat", 3.7F)57 // add as dataItem58 .addRequestInfo(59 "reqinfoDataItem",60 CborBuilder().addArray().add(1).add("item2").add("item3").end().build()61 .first()62 )6364 }.buildDoc()65 //add another docType66 .addDocType("my.cusom.docType.custom").apply {67 addParams(68 "my.custom.namespace2", listOf(69 MIDRequestParam("custom_param_nm21", true),70 MIDRequestParam("custom_param_nm22"),71 MIDRequestParam("custom_param_nm23"),72 MIDRequestParam("custom_param_nm21", true) //duplicate73 )74 )75 // add requestInfo as map76 .addRequestInfo(77 infoMap = hashMapOf(78 "reqKey1" to "reqVal1",79 "reqKey2" to "reqVal2",80 "reqKey3" to false,81 "reqKey4" to 333482 )83 )84 }.buildDoc()85 //(optional) setReaderAuthentication callback if needed86 .setReaderAuthCallback(readerAuthSigner,ReaderAuthAlgorithm.ALGO_SHA256WITHECDSA)87 //(optional) Use setMultiRequestCallback to enable multiple requests-response exchanges within same session.88 .setMultiRequestCallback(multiResCallback)89 .build()9091 if (deModel?.isMDLAsPeripheral()) {92 askLocationPermission() /* android.permission.ACCESS_COARSE_LOCATION to be added in AndroidManifest.93 you may invoke all permission dialogs beforehand to avoid this check here*/94 //mSdkClient?.sendRequest(apiConfigs, callback = mRequestCallback) //get permission and then call sendRequest95 } else {96 mSdkClient?.sendRequest(apiConfigs, callback = mRequestCallback)97 }9899 }100101 fun getRequestedParamsMap(): java.util.HashMap<String, List<MIDRequestParam>> {102 val paramMap= hashMapOf<String, List<MIDRequestParam>>()103 paramMap.put(NAMESPACE_18013_5,listOf(104 MIDRequestParam(FAMILY_NAME),105 MIDRequestParam(GIVEN_NAME),106 MIDRequestParam(BIRTHDATE),107 MIDRequestParam(ISSUE_DATE),108 MIDRequestParam(EXPIRY_DATE),109 MIDRequestParam(ISSUING_COUNTRY),110 MIDRequestParam(ISSUING_AUTHORITY),111 MIDRequestParam(DOCUMENT_NUMBER),112 MIDRequestParam(PORTRAIT),113 MIDRequestParam(MGMT_LAST_UPDATE)))114115 paramMap.put(NAMESPACE_ORG_ISO_AAMVA,listOf(MIDRequestParam(DHS_COMPLIANCE),116 MIDRequestParam(DOMESTIC_DRIVING_PRIVILEGES)))117118 return paramMap119 }
**Sample code for Reader Authentication callback implementation **
Language not specified1Reader Authentication is an optional `setReaderAuthCallback` which can be used by the integrator to implement Reader Auth for their Verifier app.2Below sample code spec illustrates how Reader Authentication callback can be implemented:34a. Add/Enable the callback in the RequestBuilder56```kotlin7 val apiConfigs = ApiConfigs.MIDRequestBuilder()8 .version("1.0")9 .addDocType("my.cusom.docType.custom").apply {10 addParams( … )11 }.buildDoc()12 …13 .setReaderAuthCallback(readerAuthSignerCallback,readerAuthAlgorithm)14 .build()1516```17b. 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 integrator18with 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]1920```kotlin21 val readerAuthAlgorithm = ReaderAuthAlgorithm.ALGO_SHA256WITHECDSA22 val readerAuthSigner=object : ReaderAuthSignerCallback {23 override fun doSignItemRequest(readerAuthenticationStructure: ByteArray?,docType:String): ReaderAuthSign? {24 // Verify SDK provides some utility functions in VIDUtils which can be used or write your own logic to generate the signature2526 val signatureBytes = VIDUtils.generateReaderAuthSignature(readerAuthAlgorithm, readerAuthPrivateKey, readerAuthenticationStructure)27 val certItem=CborBuilder().add(x509Certificate).build().firstOrNull()28 return ReaderAuthSign(signature = signatureBytes,x509Certificate = certItem)2930 }31```32c. List the required resources e.g cert, keys. at Integrator side.331. Reader 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.342. Reade Signer certificate containing the corresponding public key of the private key used in #a; which shall be sent to mdoc within the mdoc request. Integrator would submit a CSR to a valid CA to get a signer certificate.353. Reader CA certificate from CA which shall be shared by Reader to mDoc Holder which they can uses for signer certificate trust path validation
** Sample code for multiReqCallback **
Kotlin1val multiResCallback = object : MultiResponseCallback<ResponseItem?> {2 override fun onMultiResponse(3 response: ResponseItem?,4 requestCallback: MultiRequestCallback5 ): Boolean {6 /*7 * 1. process the `response` and analyse or display if needed8 * 2. check if new request is required to send: y/n9 * - if y. create a new request using ApiConfigs.MIDRequestBuilder() and send back using10 * `requestCallback.onNextRequest()`11 * - if n, return false and wait for onSuccess or onError with final response12 */13 handleMultiResponse(response,requestCallback)14 return true15 }1617 }
- Obtain the response callback for parsing the engagement QR code data scan as shown in the snippet:
Kotlin1/**2 * Request callback for sendRequest SDK api to receive and display response data from Mobile ID3 */4 val mRequestCallback = object : RequestCallback<ResponseItem?, ProgressItem> {56 override fun onSuccess(response: ResponseItem?) {7 Log.e(TAG, "Mobile ID response:$response")8 displayResponse(response as DLDataModel)9 }1011 override fun onError(error: IError?) {12 handleError(error = error as VSDKError)13 }1415 override fun onProgress(progress: ProgressItem) {16 Log.e(TAG, progress.toString())17 }1819 }
- You can cancel/terminate a transaction any time if an error occurs in the app, or if the user cancels the transaction by tapping the Back button. Cancel a transaction by calling the
cancelRequest()
method as shown in the snippet:
Kotlin1mSdkClient?.cancelRequest()2 //OR V2 client call3 mSdkClient?.terminateSession()
7.1. To close a running connection and start another connection using prepareConnection
use terminateConnection
API
Kotlin1// Available only in V2 client2 mSdkClient?.terminateSession()
Integrate NFC Handover + BLE/NFC/WiFi Use case
- Initialise NFC device Engagement
Kotlin1val apiConfigs = ApiConfigs.Builder()2 .withConfigs().apply {3 useNfcHandover()4 //setBLEMacAddress(bleMacAddress) for mac address connect use this option5 setNfcConfigs(NfcConfigs.Builder().setPresenceCheckDelay(1000)6 .addNfcDetectCallback(object:NfcConfigs.NfcDetectCallback{7 override fun onTagDiscovered(tag: Tag?): Boolean {8 // indicates new nfc tag is discovered. return true to process the tag9 // you may add / display some progress indicator for user10 // once the handover is done, feedback will be received in mDEParserCallback11 return true12 }13 })14 .build())15 //...16 }.buildConfigs()17 .build()18 mSdkClient?.initDeviceEngagement(apiConfigs, mDEParserCallback)
-
After device engagement is complete, follow the same steps as described above
-
To configure NFC or Wifi as data transfer method add configs in
ConnectionConfigs
Builder.
Kotlin1val connectionConfigs = ConnectionConfigs.Builder()2 .withConfigs().apply {3 setResponseTimeout(10000) //sdk will disconnect and return with error code 303 if transaction doesn't complete in 10 seconds4 setConnectTimeout(10000) //sdk will return with error code 206 is connection not established withing 10 seconds5 useNfc() // or useWifi() // or connectAsmDocPeripheral() or connectAsmDocCentral6 }.buildConf()7 .build()
Note:
- By default BLE mDoc Central mode is the preferred mode if multiple modes are available from mDL holder
- From Reader side verify SDK allows the integrator to configure the preferred connection mode, however if configured mode is not available, VerifySDK will try to connect using whichever mode is available with mDL holder
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" | |||
1 | ADMINISTRATIVE_NUMBER | administrative_number | Major type 3 |
2 | SEX | sex | 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 3 |
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 | ajor 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 | SIGNATURE_USUAL_MARK | signature_usual_mark | Major type 3 |
36 | ONLINE_URL_XXXX | online_url_xxxx | Major type 3 |
37 | BIRTHDATE | birth_date | Major type 3 |
38 | BIRTH_PLACE | birth_place | Major type 3 |
39 | NAME_NAT_CHAR | name_national_character | Major type 3 |
40 | FAMILY_NAME_NATIONAL_CHAR | family_name_national_character | Major type 3 //added in N19xx |
41 | GIVEN_NAME_NATIONAL_CHAR | given_name_national_character | Major type 3 //added in N19xx |
Namespace= "org.iso.18013.5.1.aamva" | //based on mDL-Implementation-Guidelines-1-0_2021.pdf | ||
1 | DOMESTIC_DRIVING_PRIVILEGES | domestic_driving_privileges | Major type 3 |
2 | DHS_COMPLIANCE | DHS_compliance | Major type 3 |
3 | NAME_SUFFIX | name_suffix | Major type 3 |
4 | ORGAN_DONOR | organ_donor | Major type 0 |
5 | VETERAN | veteran | Major type 0 |
6 | FAMILY_NAME_TRUNCATION | family_name_truncation | Major type 3 |
7 | GIVEN_NAME_TRUNCATION | given_name_truncation | Major type 3 |
8 | AKA_FAMILY_NAME_V2 | aka_family_name.v2 | Major type 3 |
9 | AKA_GIVEN_NAME_V2 | aka_given_name.v2 | Major type 3 |
10 | AKA_SUFFIX | aka_suffix | Major type 3 |
11 | WEIGHT_RANGE | weight_range | Major type 0 |
12 | RACE_ETHNICITY | race_ethnicity | Major type 3 |
13 | EDL_CREDENTIAL | EDL_credential | Major type 0 |
14 | SEX | sex | Major type 0 |
15 | RESIDENT_COUNTY | resident_county | Major type 3 |
16 | HAZMAT_ENDORSEMENT_EXPIRATION_DATE | hazmat_endorsement_expiration_date | Major type 3 |
17 | DHS_TEMPORARY_LAWFUL_STATUS | DHS_temporary_lawful_status | Major 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_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 | [{"codes": [{"sign": "Sign","value": "value","code": "C"}],"issue_date": "2018-08-09","vehicle_category_code": "A","expiry_date": "2024-06-11"}] |
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" |
given_name_national_character | Text/String | "US" |
family_name_national_character | Text/String | "US" |
Namespace = "org.iso.18013.1.aamva" | ||
DHS_compliance | Text/String | “F” = fully compliant “N” = non-compliant |
domestic_driving_privileges | Text/String | [{"domestic_vehicle_class": {"expiry_date": 0("2035-10-12 07:20:50.52Z"), "issuer_date": 0("2019-10-12 07:20:50.52Z"), "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_suffix | Text/String | “SR” |
organ_donor | Integer | 1 |
veteran | Integer | 1 |
family_name_truncation | Text/String | “N” |
given_name_truncation | Text/String | “N” |
aka_family_name.v2 | Text/String | “N” |
aka_given_name.v2 | Text/String | “S” |
aka_suffix | Text/String | “N” |
weight_range | Integer | “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_ethnicity | Text/String | “A” //Codes for race or eth- nicity of the creden- tial holder, as defined in AAMVA D20. |
EDL_credential | Integer | 1 //This field is either absent or has one of the following values: 1: Driver’s license, 2: Identification card (Applicable only in the US. ) |
sex | Integer | 1 |
resident_county | Text/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_date | Text/String | "2024-01-11" |
DHS_temporary_lawful_status | Integer | 1 // This field is either absent or has value= 1: Temporary lawful status (Applicable only in the US. ) |
Deprecations and Deletions
- Deprecated APIs/Methods/Properties from previous versions are removed
ProGuard Rules
The following code snippets should be added in the app ProGuard Rules file.
- SDK obfuscation rules:
Language not specified1-keep public class idemia.verify.sdk.** {2 public protected *;3}4-keep class org.bouncycastle.**{*;}
Release Notes
- Refer CHANGELOG.md for full release notes history.
IACA certificate file format support
- Supports following formats for IACA certificates - (.pem, .crt, .der).
Elliptic Curve Support
Operation | Curve | Specification | Curve Identifier |
---|---|---|---|
ECDH/ECDSA | P-256 | FIPS-PUB 186-4 | IANA COSE Registry |
ECDH/ECDSA | P-384 | FIPS-PUB 186-4 | IANA COSE Registry |
ECDH/ECDSA | P-521 | FIPS-PUB 186-4 | IANA COSE Registry |
ECDH/ECDSA | brainpoolP521r1 | RFC 5639 | IANA COSE Registry |
ECDH/ECDSA | brainpoolP320r1 | RFC 5639 | IANA COSE Registry |
ECDH/ECDSA | brainpoolP384r1 | RFC 5639 | IANA COSE Registry |
ECDH/ECDSA | brainpoolP512r1 | RFC 5639 | IANA COSE Registry |
ECDH | X25519 | RFC 7748 | IANA COSE Registry |
ECDH | X448 | RFC 7748 | IANA COSE Registry |
EdDSA | Ed25519 | RFC 8032 | IANA COSE Registry |
EdDSA | Ed448 | RFC 8032 | IANA COSE Registry |
ISO-18013-5 Specification Support
ISO Version | Supported |
---|---|
N1985 (published 1.0) | Yes |
N1938 | Yes |
N1818 | Yes |
N1677 | Yes |
Additions & Updates
- Session auto close when status code 20 received in response
- Fix reader flags to support Type4: NfcA/NfcB tags
- Bug fixes and Improvements
Error Codes
Error Code | Error Code Message | Description | Action Required |
---|---|---|---|
101 | Invalid QR Code | Unable to scan the QR code. | Please try again. |
102 | QR code parsing error | Unable to find some elements in the QR data item, Try again. | Try Again |
103 | QR code parsing error | DataItem(Map) is not found or empty, Unable to parse the QR code that the Mobile ID has provided. | Try again |
104 | QR code parsing error | DataItem(Array) not found or empty, Unable to parse the QR code that the Mobile ID has provided. | Try again |
105 | QR code scan error | Unable to Scan QR code may be because of invalid data or bad encoding | Try Again |
109 | Invalid cipher suite | Only cipher suite 1 (EC algorithm) is supported. | Try Again |
110 | Invalid EDeviceKey | mdoc ephemeral public point in the EDeviceKey in the DeviceEngagement structure sent by the mdoc is not on the indicated curve. | Try Again |
111 | Invalid EDeviceKey | Incorrect or unspecified curve Id, key type (kty) or x,y coordinates received in EDeviceKey DeviceEngagement structure sent by the mdoc | Try Again |
123 | Image Conversion Error | Error in convert image from bitmap to Image | Try again. |
141 | Nfc engagement error | Invalid NFC Tag, unable to read data | Try again |
142 | NFC handover error | Incorrect types for ac record,carrier record and auxiliary record | Try Again |
143 | NFC handover error | Reference length indicated longer than available bytes. | Try again |
144 | NFC handover error | Tag was lost, error during APDU transmission, tag may be out of field. | Try Again |
145 | ISO-DEP is not supported | Main Tag is not supporting ISO-DEP technology. | Try again |
146 | NFC handover error | Error with TT4 configuration | Try again |
147 | NFC handover error | Wrongly formatted Service Parameter record | Try again |
148 | NFC handover error | Error with Carrier Configuration record linking | Try again |
149 | NFC handover error | Main Initial message is null. | Try again |
150 | Nfc error - bad context | Bad context supplied - must be an Activity context | Pass the activity context in VSDKConfigs(activity) while creating VerifySDK Object, and try again |
151 | Nfc error - not enabled | NFC is not enabled. Go to settings and enable NFC | You may call VIDUtils.promptNfcSettings() to launch the NFC setting page or enable manually from setting |
152 | Nfc handover error | Error in NFC Handover, while getting NDEF TAG | |
201 | Unable to initialize BLE | Error in initializing BLE feature of this device. | The Mobile ID reader is not able to get BLE. The Mobile ID 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 | BLE connection Error | This device's Bluetooth is off. | The Bluetooth of the device is not enabled. The Mobile ID reader may abort the transaction. |
205 | BLE Scanning Error | Please provide the BLUETOOTH permissions | Try again |
206 | Connection Timeout | Unable to create communication channel with mDL device | Try again |
207 | BLE connection Error | An unexpected value exchanged during transmission | Try again |
208 | BLE Advertising Error | Failed to add BLE service | Try again |
209 | BLE L2CAP Error | Error while receiving response from mID | Try again |
210 | BLE L2CAP Error | Error while transferring request to mID | Try again |
212 | BLE Connection Error | Error in BLE state due to previous/indisposed connection(s) | |
221 | Connection mode not available | VerifySDK is not able to setup connection with Mobile ID using configured connection type/mode. | Try again |
281 | BLE Permission Error | Required permission BLUETOOTH_ADMIN not found in app AndroidManifest.xml | |
282 | Location Permission Error | Required permissions ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION not found in app AndroidManifest.xml | Please declare the required permissions in your app AndroidManifest.xml |
283 | Location Permission Error | Required permission ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION not granted | User must accept the permission when permission dialog is shown, check app permission settings to manually accept all required permissionsr |
284 | BLE Permission error | Required permission BLUETOOTH_CONNECT not found in app AndroidManifest.xml | android.permission.BLUETOOTH_CONNECT permission should be added in your app AndroidManifest.xml |
285 | BLE Permission error | Required permission BLUETOOTH_CONNECT not granted | User must accept the permission when permission dialog is shown, check app permission settings to manually accept all required permissions |
286 | BLE Permission error | Required permission BLUETOOTH_SCAN not found in app AndroidManifest.xml | android.permission.BLUETOOTH_SCAN permission should be added in your app AndroidManifest.xml |
287 | BLE Permission error | Required permission BLUETOOTH_SCAN not granted | User must accept the permission when permission dialog is shown, check app permission settings to manually accept all required permissions |
288 | BLE Permission error | Required permission BLUETOOTH_ADVERTISE not found in app AndroidManifest.xml | android.permission.BLUETOOTH_ADVERTISE permission should be added in your app AndroidManifest.xml |
289 | BLE Permission error | Required permission BLUETOOTH_ADVERTISE not granted | User must accept the permission when permission dialog is shown, check app permission settings to manually accept all required permissions |
290 | Error in connection | Can't create connection without device engagement. | initDeviceEngagement should be called before calling PrepareConnection |
291 | Error in connection | Connection terminated by client. | Call prepareConnection API to create new connection |
292 | Error in connection | Can't send request without prepareConnection. | prepareConnection api should be called before sendRequest |
301 | Transaction Cancelled | Transaction has been cancelled or closed. | Connection closed due to an error, try again. |
302 | Connection Lost | Unfortunately has device disconnected; device may be out of BLE/NaN.NFC range | The Mobile ID reader may abort the transaction. Try Again |
303 | Timed Out, Try again | Transaction has timeout or cancelled | Try Again |
304 | Request Incomplete. | Please select one or more attributes to be included in the request to the Mobile ID | Try Again |
305 | Incomplete Request | An 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 reader may abort the transaction. |
306 | Request Rejected | The Mobile ID indicates that the request is rejected. | BLE connection failure. he Mobile ID reader may abort the transaction. |
307 | The Mobile ID Reader Authentication Error | The Mobile ID indicates there is an error with Mobile ID Reader authentication | Try Again |
308 | General Error | The Mobile ID returns an error without any given reason. | The Mobile ID reader may inspect the request, ensure request is complete, and resend. The Mobile ID reader may abort the transaction. |
309 | Invalid Request | Request can't contain more than 2 age_over_nn as request attributes | Try Again |
310 | Error in reader authentication | callback or algorithm can not be null or empty | Try Again |
311 | Error in request data | Request params are null or invalid; Can't proceed | Try Again |
312 | Session Terminated by mDoc | SessionData status 20 is received from mDoc | Try Again |
400 | Error in response data received. | Response data is malformed or nil | Try Again |
401 | Parsing Error | An Mobile ID encountered data element that is not well-formed (e.g., invalid initial=byte) and failed decoding data. The Mobile ID does not return any data but the error message. | The Mobile ID reader may inspect the request, ensure request is complete, and resend. The Mobile ID reader may abort the transaction. |
402 | Invalid Format | The Mobile ID cannot process the requested data element due to a formatting error. | Try Again |
403 | Data Not Found | The requested NameSpace or data element within a NameSpace is not found. | Try Again |
404 | Data Request Denied | The release of requested data element was rejected by the Mobile ID holder. | Try Again |
405 | Data Not Returned | The Mobile ID does not provide the requested data element without any given reason. | Try Again |
406 | CBOR decoding Error | The Mobile ID indicates an error during CBOR decoding that the data received is not valid CBOR | Try Again |
407 | CBOR Validation Error | The Mobile ID indicates an error during CBOR validation, e.g. wrong CBOR structures | Try Again |
451 | Certificate Path Error | Either Path is invalid or inaccessible or not a folder path or folder is empty | Provide valid path and check required permissions to read/write the files are granted by user |
500 | Generic Error | Generic Error from VerifyID abstraction layer, concrete class must override to throw actual error | Try Again |
701 | Unable to discover Wi-Fi Aware service | Wi-Fi Aware Service is not discovered. | Try Again |
702 | Device Doesn't Support Wifi | This device does not support wifi feature. | Try Again |
703 | Wifi Aware Connection Timeout | Unable to establish socket connection, try again. | Try Again |
704 | WIFI is OFF | This device Wi-Fi is disabled, enable WiFi and try again. | Try Again |
705 | WiFi aware Network is Lost | Wifi aware connection network lost, try again | Try Again |
706 | Error in WiFi communication | Incorrect HTTP status code, expected 200 but found other. | Try Again |
751 | NFC data transfer error. | The Mobile ID Request is null or malformed | Try Again |
752 | NFC data transfer error | Response data is null or malformed, try again. | Try Again |
753 | NFC connection error | ISODep not connected; make sure to tap on back of other device to setup the NFC connection. | Try Again |
754 | NFC data transfer error | Error in receiving response from The Mobile ID, try again. | Try Again |
755 | NFC data transfer error | Error in NFC data transfer service, try again. | Try Again |
756 | NFC connection error | NFC hardware is disabled, Enable NFC from settings and try again. | Try Again |
757 | NFC connection error | NFC not supported as a system feature. | Try transfer mode other than NFC |
758 | NFC data transfer error | Tag was lost;Error during APDU NFC data transfer transmission,tag may be out of field | Try Again |
Test Samples
QR + BLE Sample
The following screen shows a scan of the QR code in the Mobile ID App.
Note: This screenshot is only for device engagement QR code testing. The full QR + BLE scenario will only work with a real device with the IDEMIA Mobile ID App installed.