We recently had a requirement to perform customer eKYC using a fingerprint scanner device in an ElectronJS based Windows application. If you want to do the same, then let me share an insight- it can’t be done with just any fingerprint scanner; you will need an AVDM for that. You must be wondering what an AVDM is? AVDM is short for “Aadhar Verification Device Manager” it is nothing but a simple fingerprint scanning device that a UIDAI authorized vendor manufactures. For the device, the vendor must get UIDAI’s permission and should comply with specific security practices.
The device we chose was Mantra’s MFS100. Device usages are well documented, and the device is user-friendly. It can be easily plugged in using a USB connection and exposes REST APIs to make it platform-independent and language-independent. The device itself is not that important because any vendor UIDAI authorizes can expose based on similar APIs for using it.
Is it easy to use and document? Then, why am I writing one more article and adding it to the already available documentation list? While the device usages are pretty straightforward, are they used for generating fingerprint data for eKYC verification? Well, I will not say that finding the right solution was easy. The problem I faced is that there is not a single place to find everything you need; the data is scattered in many areas. I had to go through tons of resources, including UIDAI’s eKYC API documentation and connect with many people to get to the right solution. The trickiest part is that you’ll never know if the generated data is correct until you perform an eKYC verification check, as we’ll get the information even if we are missing a thing or two, but the eKYC verification will fail eventually. I’ll explain my experience of integrating the AVDM device, and I hope you will find this helpful.
As I said, we need an AVDM to capture the biometric data, but that’s not all. AVDM is incomplete without an RD service; the RD service registers the fingerprint device as an AVDM on the vendor’s management servers, hence the “Register Device” service. RD service is also responsible for interacting with vendor management servers for encrypting biometric data. Let’s move on and install the device driver and RD service together.
How to install Mantra device driver and Mantra RD service in windows?
Just go to Mantra’s download page, enter the captcha and you’ll land on the page with all the drivers. Download the device driver for MFS100 and its RD service from the page.
Once the driver and RD service are downloaded, install them in administrator mode (right-click on the .exe file and choose “Run as administrator” from the options menu).
It’s important to note that the RD service will not work if the installation is done without admin access because the setup requires access to the “system32” folder in the Windows directory. Driver and RD service installation is a one-time task, the service is bound to Windows boot and restarted when the system restarts.
Voila!! It’s done. We have the system ready for some serious action!
How to check the device status?
When installed, RD service takes up one of the ports from 11100 to 11105. Check the port on which the RD service is running beforehand, in most cases, it’s going to be 11100 unless some other service is already running on the port.
RD service exposes a few simple REST APIs that accept and send XML payloads. An interesting point to note here is that none of the RD service REST APIs uses standard HTTP methods like GET, POST, PUT etc.
The first one is the “Discover AVDM” API, cURL request for the API looks like this –
curl –location –request RDSERVICE ‘http://127.0.0.1:11100‘
Status response –
<?xml version=”1.0″?>
<RDService status=”READY” info=”Mantra Authentication Vendor Device Manager”>
<Interface id=”DEVICEINFO” path=”/rd/info” />
<Interface id=”CAPTURE” path=”/rd/capture” />
</RDService>
Did you notice the status field in the response? Anything but READY is an error. Please ensure that the device is properly connected to the machine if you have an error. Two important data points are also present in the response here – API URIs and corresponding HTTP methods for getting device information & for capturing biometric data.
How to get the device information?
To get the endpoint for the “Device Info” API, we need to concatenate the base URL with the path received in the “Discover AVDM” API response.
cURL request for the API looks like this –
curl –location –request DEVICEINFO ‘http://127.0.0.1:11100/rd/info‘
Device info response –
<?xml version=”1.0″?>
<DeviceInfo dpId=”MANTRA.MSIPL” rdsId=”MANTRA.WIN.001″ rdsVer=”1.0.3″ mi=”MFS100″ mc=”MgTWFudHJhIFNvZn…w=” dc=”c4148a54-a544-4c41-8b31-85e4c4148b31″>
<additional_info>
<Param name=”srno” value=”98712312″ />
<Param name=”sysid” value=”DBQBQWB80NVP90L793JG” />
<Param name=”ts” value=”2022-01-13T19:00:00+05:30″ />
</additional_info>
</DeviceInfo>
We received device information and RD service details in the response. Check out some of the important values and what these values mean –
- dpId is a unique device provider ID assigned to the vendor by UIDAI.
- rdsId is a unique RD service ID assigned to the vendor’s RD service by UIDAI.
- rdsVer is the RD service version installed in the system.
- mi is the model ID for the device.
- mc is a public key assigned to the device when it’s registered in the vendor’s management server.
- dc is a unique code assigned to the device.
How to capture fingerprint data for EKYC purposes?
We will start with how biometric EKYC verification works. As the first step, our application sends a capture request to the RD service, which in turn triggers the device to start scanning. Once the biometric data is collected, RD service processes the data and encrypts it. Finally, the RD service prepares the PID data block and sends it back to our application, this PID data can be verified by requesting “KUA” (Aadhar User Agency or “AUA” with KYC permission, it’s a separate entity from the device vendor) for EKYC verification.
Below is the cURL request for the “Capture” API. For the “Capture” request too, we need to concatenate the base URL with the path received in the “Discover AVDM” API response –
curl –location –request CAPTURE ‘http://127.0.0.1:11100/rd/capture‘ \
–header ‘Content-Type: application/xml’ \
–data-raw ‘<?xml version=”1.0″?>
<PidOptions ver=”1.0″>
<Opts fCount=”1″ fType=”0″ iCount=”0″ pCount=”0″ format=”0″ pidVer=”2.0″ timeout=”10000″ posh=”UNKNOWN” env=”P” wadh=”E0jzJ/P8UopUHAieZn8CKqS4WPMi5ZSYXgfnlfkWjrc=”/>
<CustOpts>
<Param name=”mantrakey” value=”undefined” ></Param>
</CustOpts>
</PidOptions>’
Just specify a few options in the request body. These must be correct to get the right kind of data, as I had mentioned earlier. We will get the data anyway even if we miss a few things, but that does not mean all the parameters are correct. Let’s go through the options we have sent in the request –
- fCount is the number of fingers we are capturing in the request. fCount varies between “0” and “10”. The device which we are using, MFS100, is used for capturing only one finger at a time.
- fType can have two possible values “0” for “FMR” (Fingerprint Minutiae Records) or “1” for “FIR” (Fingerprint Image Records). As FMR is the recommended method for fingerprint capturing, so we’ll go with value “0” here.
- iCount is the number of iris, this value is “0” for us because we are not scanning iris here. iCount can vary between 0 and 2.
- pCount specifies face count for scanning. Use “0” when not scanning the face, “1” while scanning the face.
- format specifies the type of data format we need in the response. “0” is for XML and “1” is for ProtoBuf. ProtoBuf is a new mechanism designed by Google for serializing structured data.
- pidVer is the version for the PID data type that we’ll receive in the response. “2.0” is the latest one and will work with new Aadhaar APIs.
- timeout specifies the number of milliseconds after which the capture request times out if no fingerprint is detected.
- posh specifies finger/ iris type to be captured. “UNKNOWN” value means that any finger or iris can be scanned.
- env can have three possible values – “S” for staging, “PP” for pre-production and “P” for production.
- wadh has EKYC API options. We get this value by concatenating EKYC options, then encrypting the resultant string using the SHA256 algorithm and then finally encoding it in BASE64 format. EKYC options are –
- ver is the EKYC API version, here I’m using the latest version available i.e., “2.5”.
- ra is the resident authentication type that means the kind of verification we are performing. “F” is for finger, “I” for iris, “O” for OTP and “P” for the face. These values can be combined as well, like “FO” for fingerprint and OTP verification. This option must match with the options specified for fCount/ iCount/ pCount, otherwise, the EKYC verification will fail.
- rc represents explicit consent of the customer for biometric verification. The only possible value is “Y”, any other value results in an error response.
- lr value should be “Y” if local language data is required in the response in addition to English, “N” is for English only.
- de specifies who decrypts the biometric data when the data is forwarded for EKYC verification. If this is set to “N” then “KUA” will decrypt the data, otherwise, their parent entity “ASA” will decrypt the data.
- pfr specifies the print format request option. If it is set to “Y” then PDF print format is attached in the response, only XML is returned if the value is set to “N”.
- Finally, wadh can be calculated with these values. wadh = BASE64(SHA256(ver + ra + rc + lr + de + pfr))
Phewww!! That was a lot. Now that the request options are explained, take a look at the capture response –
<?xml version=”1.0″?>
<PidData>
<Resp errCode=”0″ errInfo=”Success” fCount=”1″ fType=”0″ nmPoints=”46″ qScore=”71″ />
<DeviceInfo dpId=”MANTRA.MSIPL” rdsId=”MANTRA.WIN.001″ rdsVer=”1.0.3″ mi=”MFS100″ mc=”MgTWFudHJhIFNvZn…w=” dc=”c4148a54-a544-4c41-8b31-85e4c4148b31″>
<additional_info>
<Param name=”srno” value=”98712312″ />
<Param name=”sysid” value=”DBQBQWB80NVP90L793JG” />
<Param name=”ts” value=”2022-01-13T19:00:00+05:30″ />
</additional_info>
</DeviceInfo>
<Skey ci=”20220113″>rW1yvtbOFKISFANC…g==</Skey>
<Hmac>ib9Amw/J6TQ78aVTt…ZZh</Hmac>
<Data type=”X”>MgTWFudHJhIFNvZn…wg==</Data>
</PidData>
We received device information and captured fingerprint data (SKey, Hmac and Data) in the response. Here –
- errCode value “0” indicates that the capture was successful, in case of an error we get a helpful error message in errInfo.
- nmPoints in the response is for the number of captured minutiae points. Minutiae points are the points where lines in the fingerprint end or fork out. Values between 25 and 80 are considered good.
- qScore indicates normalized quality score for the captured data. This varies from “0” to “100”.
Easier than you thought in the beginning, isn’t it?
Debugging common issues
- API requests to the RD service in the user’s machine (user’s localhost) may fail with the error blocked:other if an ad-blocker is active, please turn off the ad-blocker to proceed.
Final thoughts
As you may have understood from the above explanation, these APIs can be used for any Aadhaar- based biometric verification like fingerprint, iris, or face verification. All we need to do is to tweak the request body a little and that’s about it.
I have implemented fingerprint flow in a React application, the code is hosted in a Git repo here. Also, this application is deployed in Heroku.
Hope this helps, till then happy coding!