Performing BWS tasks with JavaScript using REST

event_note June 11, 2014

We already provided some .NET samples to access the BioID Web Service (BWS) using SOAP requests, e. g. with the BWS command line interface. It's time to give you a sample that uses the RESTful BWS extension to perform BWS tasks.

The sample code we want to summon up here comes from a real live HTML5 / JavaScript application, which is our implementation of a web based unified user interface for the BioID Web Service. It makes use of a HTML5 feature called the HTML5 Media Capture and Streams API, which allows us to capture images from a web camera. The JavaScript implementation is based on jQuery. You can open the user interface directly by calling into the BWS GUI Extension. We also provide some sample calls into this user interface on our Playground web site.

How does the RESTful BWS Extension API work?

Before you can start using the BWS Extension, you need to have access to a BWS installation of course. If you don't have access to a BWS installation yet, you can register for a free trial instance. As soon as you have your BWS access information available, you can register a BWS client application (in the BWS Portal) to get a BWS App-ID and App-Secret, which are required to call into the BWS Extension. 

Please note that all REST API methods use the BWS Extension base URI https://bws.bioid.com/extension (except if you have your own BWS installation where you have to use the host name of your BWS installation of course).

Now, the first thing you have to do for every BWS task you want to perform, is to fetch a BWS Token using the BWS Token Extension.

As the token request requires your BWS App-ID and App-Secret, the token is typically requested by some server-side code. It is not recommended to request a token directly from a client application as long as you cannot ensure that your App-Secret doesn't get compromised!

In the Token Extension documentation you can find a sample of how to request a token for .NET, here is another one using the Windows PowerShell:

$x = "595520272.6.app.bioid.com:DummyAppSecret"
$h = @{"Authorization" = "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::GetEncoding("iso-8859-1").GetBytes($x))}
$token = Invoke-WebRequest "https://bws.bioid.com/extension/token?id=595520272.6.app.bioid.com&bcid=bioid.42.12345" -Header $h

You can request a token similar to the one with the sample above at our BWS Extension Test page.

As you now have a token issued, you typically return it or send it to the client application where the next steps are performed.

Performing the BWS tasks

In the sample script attached to this post you find a lot of code handling the capturing of video samples, which is not so interesting in the context of this post. The more interesting part is, what happens as soon as we have found an image that we want to upload to the BWS for face recognition tasks, and finally, what happens as soon as we uploaded enough images, so we can finally perform the biometric operation. Please note that the BWS Extension currently only supports training and verification of the face trait.

Both tasks, upload and biometric operation are performed by simple Ajax calls which both use a BWS token that previously has been created and provided to the script from outside. You can find the calls in the attached script in the methods upload() and performTask(). The upload looks something like this (for simplicity the code has been shortened):

function upload() {
    uploading++;
    // create (gray-) png from the working canvas
    var dataURL = settings.color ? copycanvas.toDataURL() : bws.toGrayDataURL(copycanvas);
    // call BWS Extension via Ajax
    var jqxhr = $.ajax({
        type: "POST",
        url: "/extension/upload",
        data: dataURL,
        // don't forget the authentication header
        headers: { "Authorization": "JWT " + token }
    }).done(function (data, textStatus, jqXHR) {
        uploading--;
        if (data.Accepted) {
            uploaded++;
        } else {
            // handle data.Error which typically is NoFaceFound or MultipleFacesFound
        }
        if (uploaded >= settings.recordings && uploading === 0) {
            // go for biometric operation
            performTask();
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        // ups, call failed, typically due to Unauthorized, BadRequest or InternalServerError
    });
}

The corresponding function that performs the biometric operation looks something like this (again shortened a little bit):

function performTask() {
    var url;
    if (settings.task === 'enrollment') {
        // go for enrollment
        url = '/extension/enroll?livedetection=true';
    } else {
        // or for verification
        url = '/extension/verify?livedetection=true';
    }
    // call BWS Extension via Ajax
    var jqxhr = $.ajax({
        type: "GET",
        url: url,
        headers: { "Authorization": "JWT " + token }
    }).done(function (data, textStatus, jqXHR) {
        if (data.Success) {
            // enroll or verify succeeded -- we are done.
        } else {
            var err = data.Error ? data.Error : "NotRecognized";
            // react on err, e.g. NoTemplateAvailable or NotRecognized
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        // ups, call failed, typically due to Unauthorized, BadRequest or InternalServerError
    });
}

How to use the attached script


Although the script is intended to be used with the BWS unified user interface, feel free to also use it (with or without modifications) on your web site. The usage is very simple:

Assuming you have at least the following HTML elements on your web page

    <button id="bwsmirror" style="display:none"></button>
    <button id="bwsstart" style="display:none"></button>
    <div id="bwserror" style="display:none"></div>
    <div id="bwsmessage"></div>
    <canvas id="bwscanvas"></canvas>
    <canvas id="bwsmotionbar"></canvas>
    <!-- also load the required scripts, e.g. -->
    <script src="jquery.js"></script>
    <script src="bws.capture.js"></script>

you can start with a jQuery script as follows:

var capture = null;
    var executions = 3;
    var token = "the token needs to be requested and filled in here by your web server";
    $(document).ready(function () {
        capture = bws.initcapture(
            document.getElementById('bwscanvas'),
            document.getElementById('bwsmotionbar'),
            token,
            {
                task: "verification"
            });
        onStart();
    });
    function onStart() {
        capture.start(function () {
            // bws capture is running - enable mirror and of course start
            $("#bwsmirror").show().click(capture.mirror);
            $("#bwsstart").show().click(function () {
                $("#bwsstart").hide();
                capture.startCountdown(function () {
                    capture.startRecording();
                });
            });
        }, function (error) {
            // an error occurred during startup
            if (error !== undefined) {
                $("#bwserror").show().html("Video capture failed to start with error: " + error);
            } else {
                // no error info typically says that browser doesn't support getUserMedia
                $("#bwserror").show().html("Your browser does not support the HTML5 Media Capture and Streams API.");
            }
        }, function (error, retry) {
            // done, maybe with error
            capture.stopRecording();
            executions--;
            if (error !== undefined && retry && executions > 0) {
                // if failed, restart if retries are left, but wait a bit until the user has read the error message!
                setTimeout(function () { 
                    capture.startCountdown(function () { 
                        capture.startRecording(); 
                    });
                }, 1800);
            } else {
                // done: redirect to caller -> url needs to be provided by your server
                // Note that the server typically uses the provided token and the 
                // BWS Result Extension to fetch the result generated here.
                var url = "https://127.0.0.1/bwscallback?access_token=" + token;
                if (error !== undefined) {
                    url = url + "&error=" + error;
                }
                window.location.replace(url);
            }
        }, function (status, message, dataURL) {
            // the function used to inform us about the current bws capture status 
            if (status !== 'DisplayTag') { // challenge-response messages are not supported in this sample
                // just display the status code on the screen
                $("#bwsmessage").html(status);
            }
            // some status codes you might be interested in
            if (status === 'Uploading') {
                // begin an upload
            } else if (status === 'Uploaded') {
                // successful upload (we should have a dataURL)
            } else if (status === 'NoFaceFound' || status === 'MultipleFacesFound') {
                // upload failed
            }
        });
    };

Name Version Published
bws.capture.js 1 2017-12-13 14:44