Read Emirates ID in a Web Application






4.50/5 (6 votes)
Read Emirates ID in a web application, using JavaScript, chrome extension and desktop application
Introduction
As of writing this document, the only applicable way to read emirates ID is to have a desktop application. The official SDK provided by Emirates ID authority included some Java applet examples which will not work anymore on recent browsers. But everyone is going now to web applications instead of desktop applications, so how can we design a workaround to achieve this?
Background
For security reasons, Java applet is obsolete in recent browsers, and this does not end here. In Chrome, you cannot run a client EXE from your web application. You cannot access the clipboard... Ok! you cannot directly, but you can using extensions.
Using the Code
We have to use the official SDK, so we need a desktop application; however, using Chrome extension, you can execute the desktop application in the background. That application will read the Emirates ID data, push the data to the clipboard, then close. Once closed, the chrome extension will read the clipboard, and send the data back to the webpage.
Look at the image below to understand the general concept:
Now, let us start with the solution.
A. Create the Desktop Application
Create a simple console application, that
- reads Emirates ID
- serializes it into JSON format
- pushes it to clipboard
- then closes
I will not go through the creation of the EXE application, as you can find the source code on github. Also, this article is not to explain how we read the Emirates ID from a desktop application. However, this application must use the official SDK from the Emirates ID Authority.
Code sample:
[STAThread]
static void Main(string[] args)
{
var model = Controller.CreateFromEIDReader();
if (model.HasData)
{
Clipboard.SetText(Newtonsoft.Json.JsonConvert.SerializeObject(model));
}
else
Clipboard.SetText("NO DATA");
}
B. Authorize Application with Chrome
Chrome cannot call EXE unless it's pre-authorized. Don't worry, authorization is very simple, and it uses chrome Native Messaging, so please refer to the official documentation.
- Copy the EXE application, created in the previous step, with all required DLLs to a new folder.
- Create a json file called ae.eid.chrome.json.
- Add a
Key
to the registry to define a unique name of your application, and let it point to a json file. The json file explains what to run and who can run the application. The easiest way is to create a batch file in the same directory and add the following code:
REG ADD "HKLM\Software\Google\Chrome\NativeMessagingHosts\ae.eid.chrome"
/ve /t REG_SZ /d "%~dp0ae.eid.chrome.json" /f
Quote:%~dp0 is the current folder from where you run the command.
So here we are saying:
Quote:Hey chrome... you can run the application
ae.eid.chrome
, and to know how please check the fileae.eid.chrome.json
So what is there in the ae.eid.chrome.json
?
Two values are important to us here:
path
to specify the EXE fileallowed_origins
to specify which chrome extension can call this EXE. This is the chrome extension id that you will create right now.
{
"name": "ae.eid.chrome",
"description": "chrome extension to read EID",
"path": "EIDSampleConsole.exe",
"type": "stdio",
"allowed_origins": [
"chrome-extension://elgjklijpoecdfbjejecncdpggdphnle/"
]
}
C. Create Chrome Extension
The main file in any Chrome Extension is the manifest. Other than that, a Chrome extension can have many other files depending on what you want to achieve. In our case, I'm using a content_script
and a background
process. So what are these files?
The background
process is isolated from the web pages opened in Chrome. This means it cannot contact the Chrome tabs directly. It has to go through the content_script
. content_script
can contact both the background
process and the pages opened in Chrome. Being isolated, the background
process can call an EXE, and read the Clipboard data. Both functions are not allowed directly in Chrome.
Quote:In my case, the background file is
eid.js
, the content_script iscontent_script.js
, and since I use jquery, I also add the jquery
manifest.json
Any Chrome extension will have a manifest.json file. It lists the behavior and the permissions of the extension. The most important permissions required are nativeMessaging
and clipboardRead
. It's here also where we specify the content_script files and the background
file. You can notice the listing of jquery
because I'm using some jquery in the content_script file, and not only JavaScript.
{
"name": "EID Reader",
"version": "1.0",
"manifest_version": 2,
"description": "Read Emirates ID",
"permissions": [ "contextMenus", "activeTab", "clipboardRead", "nativeMessaging" ],
"icons": {
"16": "eid16.png",
"48": "eid48.png",
"128": "eid128.png"
},
"background": {
"scripts": [ "eid.js" ]
},
"content_scripts": [
{
"matches": [ "http://*/*", "https://*/*", "file://*/*"],
"js": [ "content_script.js", "jquery-3.3.1.js" ],
"all_frames": true,
"run_at": "document_start"
}
]
}
content_script.js
This file is playing a role of translator. It can listen to whatever happens in your web pages, and transfer these actions to the background process by sending messages. It can also receive messages from background process and transfer it again to the web pages. Keep in mind that your web pages cannot access the background process directly, and it has to be through content_script
.
Technically, content_script
will contain two listeners: one to receive messages from web pages, and another one to receive messages from background process.
// Listener to catch the event raised by the webpage button
document.addEventListener("EID_EVENT", function (data) {
// send message to background process to read emirates ID and send back the data
chrome.runtime.sendMessage("test", function (response) {
});
});
// Listener to catch the data coming from the background process
chrome.extension.onMessage.addListener(function (msg, sender, sendResponse) {
if (msg.action == 'EID_DATA') {
//Parse the data and fill the form accordingly
try {
var json = $.parseJSON(msg.response);
$(json).each(function (i, val) {
$.each(val, function (key, value) {
if (key == 'EIDNumber')
$("#txtNumber").val(value);
if (key == 'Name')
$("#txtName").val(value);
if (key == 'Email')
$("#txtEmail").val(value);
if (key == 'PassportNumber')
$("#txtPassport").val(value);
});
});
}
catch (e) {
var error = "error" + e;
}
}
});
eid.js
This is where we do the main processes. Here, we will call the EXE application, and here is where we read the clipboard. Here is also where we send the data back to content_script
, which will parse it and push it to web pages.
Technically, this will have a listener to receive messages from content_script
. Once received, it calls the EXE application asynchronously, and will wait until the EXE finish his task (Read Emirates ID, and put it in clipboard). Once finished, an event will be fired, to read the clipboard and send it to content_script
to parse it and push it to the web page.
var port = null;
var tabId = null;
/* listener for messages coming from the content_scrip */
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
tabId=sender.tab.id;
var hostName = "ae.eid.chrome";
port = chrome.runtime.connectNative(hostName);
port.onDisconnect.addListener(onDisconnected);
});
/* THIS WILL BE CALLED ONCE EXE FINISH */
function onDisconnected() {
port = null;
SendResponse();
}
function SendResponse() {
//create a textarea, focus on it,
//and make a "paste" command to get the clipboard,
//then send the pasted value back to the content_script
bg = chrome.extension.getBackgroundPage();
bg.document.body.innerHTML = ""; // clear the background page
var helper = null;
if (helper == null) {
helper = bg.document.createElement("textarea");
helper.style.position = "absolute";
helper.style.border = "none";
document.body.appendChild(helper);
}
//Focus the textarea
helper.select();
// perform a Paste in the selected control, here the textarea
bg.document.execCommand("Paste");
// Send data back to content_script
chrome.tabs.sendMessage(tabId,
{ action: "EID_DATA", response: helper.value }, function (response) { });
}
Add Extension to Chrome
- Open Chrome and type
chrome://extensions/
- Press on
Load unpacked
- Select the extension folder
- Chrome will load the extension and give it an id.
Quote:Remember to copy the extension id and put it in the file
ae.eid.chrome.json
to authorize this extension to execute the exe application.
Test the solution
Now create a web page, add a button that raise an event, and add few inputs to be filled by the data captured from Emirates ID.
<body>
<div class="form-group">
<a class="btn btn-primary" href="javascript:readeid();">Read EID</a>
</div>
<div class="form-group">
<label for="txtNumber">Number</label>
<input type="text" class="form-control" id="txtNumber" placeholder="Number">
</div>
<div class="form-group">
<label for="txtName">Name</label>
<input type="text" class="form-control" id="txtName" placeholder="Name">
</div>
<div class="form-group">
<label for="txtEmail">Email address</label>
<input type="email" class="form-control" id="txtEmail" placeholder="Email">
</div>
<div class="form-group">
<label for="txtPassport">Passport</label>
<input type="text" class="form-control" id="txtPassport" placeholder="Passport">
</div>
<script>
var readeid = function () {
var event = document.createEvent('Event');
event.initEvent('EID_EVENT');
document.dispatchEvent(event);
}
</script>
</body>
Summary
Remember, this is a workaround, not a native solution. Native solution must come from the SDK developers.
For more information, please visit the project on github.