Skip to content

Commit

Permalink
First release of HTML5 integration examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Joe-Palmer committed Jun 4, 2018
0 parents commit 82bfc15
Show file tree
Hide file tree
Showing 12 changed files with 1,117 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea/
264 changes: 264 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
# iProov HTML5 Integration Demo
The iProov HTML5 Integration Demo illustrates a range of integrations with the HTML5 client. It makes use of the [Web Components](https://www.webcomponents.org/introduction) APIs which are supported by most modern browsers and uses the [Polymer Project](https://www.polymer-project.org) to add support where they are not yet available.

Currently the HTML5 client supports **Chrome v58+**, **Opera v45+** and **Safari v11+**. Compatibility with Firefox and Edge is coming soon.

## Setup
To run the demo, clone or download this repository and serve the root directory from localhost. See the specific backend integration (e.g. [PHP](./php/README.md)) for more details.

## Introduction
The HTML5 client integration requires backend API calls to our [REST API](https://secure.iproov.me/docs.html) and frontend integration to your web page.

### Backend
When starting an iProov transaction (or claim), you would first need to generate an [enrolment](https://secure.iproov.me/docs.html#operation/userEnrolServerToken) or [verification](https://secure.iproov.me/docs.html#operation/userVerifyServerToken) token, which can be done as part of the page load or with AJAX. You would then need to pass the token to your frontend to initialise the HTML5 client.

After receiving the result from the HTML5 client, you must then confirm its authenticity by calling the validate API from your backend on page submission or with AJAX.

> The REST API should always be called from your backend so as to never expose your secret to your client application.
> Always call the validate API from your backend after receiving a result; never trust the result provided directly from the HTML client.
### Frontend
Once an iProov token has been generated by your backend, you should pass it to the HTML5 client using one of the [integration methods](#integration) described below.

After a successful iProov, the result must be validated by the backend before granting the user any privileges.

In these examples, the token is generated and validated using AJAX (in the register/login demo) and form submission (for the integration examples) by passing the following data to the backend:
- **user_id** - the email address provided by user
- **action** - the specific endpoint to call:
- _token_ - generate a unique 64 character token for the client
- _validate_ - check the validity of the result provided by the client
- **type** - the type of iProov to perform:
- _enrol_ - enrol a user's face against the provided user_id
- _verify_ - verify a user's face against the provided user_id
- **example** - the integration example to load:
- _[html](./examples/html.html)_ - embed the custom element HTML within the page
- _[javascript](./examples/javascript.html)_ - inject the component after calling the constructor
- _[jquery](./examples/jquery.html)_ - inject the custom element HTML onto the page

## Integration
To include the iProov HTML5 client on your page, add the following JavaScript to your page:

```html
<script src="https://secure.iproov.me/html5/v1/client"></script>
```

Now the HTML5 client is ready to initialise. This can be done with HTML or JavaScript.

### HTML
The simplest way to embed the HTML5 client is to add a custom element to your HTML output where you want the Web Component to appear:

```html
<iproov-me token="***YOUR_TOKEN_HERE***" type="enrol"></iproov-me>
```

### JavaScript
Alternatively, you can initialise the element by calling the **IProovMe** constructor and injecting the component onto your page where you want it to appear:

```javascript
window.addEventListener('WebComponentsReady', function(event) {
var component = new IProovMe({
token: '***YOUR_TOKEN_HERE***',
type: 'enrol'
});
document.getElementById('element-id').appendChild(component);
});
```

### jQuery

The HTML cal also be injected directly onto the page as in this jQuery example:

```javascript
window.addEventListener('WebComponentsReady', function(event) {
$('#element-id').append($('<iproov-me token="***YOUR_TOKEN_HERE***" type="enrol"></iproov-me>'));
});
```

> Note that JavaScript methods are run after the **WebComponentsReady** event to ensure that the client is ready to be injected.
## Events
There are a set of [CustomEvents](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) that can be used to integrate bespoke functionality. Events are bound directly to the `<iproov-me>` element after the [WebComponentsReady](https://www.webcomponents.org/polyfills#the-webcomponentsready-event) event.

### Details

Every event has a [detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) property which contains data relating to that event. The following details are present for every event:

```json
{
"cameras": 1,
"token": "t0k3n...",
"type": "enrol"
}
```

The available events are detailed below with any extra properties that are supplied:

| Event | Extra Properties | Description |
|-----------------|-----------------------|-----------------------------------------------------------------------|
| **ready** | None | iProov has initialised successfully |
| **started** | None | The user has started iProov by launching into fullscreen |
| **aborted** | *feedback, reason* | The user has aborted iProov by exiting fullscreen |
| **streamed** | None | The user has finished streaming and the client has exited fullscreen |
| **progress** | *percentage, message* | iProov has published a progress update for the authentication |
| **passed** | None | The authentication was successful so the result can now be validated |
| **failed** | *feedback, reason* | The authentication was unsuccessful so the user needs to try again |
| **error** | *feedback, reason* | iProov encountered an error while processing the authentication |
| **unsupported** | *feedback, reason* | The browser does not support using iProov |

All possible properties of the event's **detail** property are described below:

| Property | Events | Description |
|----------------|---------------------------------------|------------------------------------------------------------|
| **cameras** | All | The total number of cameras available to the browser |
| **token** | All | The token associated with the authentication attempt |
| **type** | All | The type of authentication (enrol or verify) |
| **percentage** | *progress* | A percentage (between 0 and 100) representing the progress |
| **message** | *progress* | A user friendly description of the current progress stage |
| **feedback** | *aborted, failed, error, unsupported* | A fixed feedback code for making logical decisions |
| **reason** | *aborted, failed, error, unsupported* | An English description of the reason for the event |

In the case of the **aborted**, **failed**, **error** and **unsupported** events, the _feedback_ code can be used for dealing with special cases and the _reason_ can be displayed to the user. The following are some of the possible responses:

| Feedback | Reason | Event |
|---------------------------------------|-------------------------------------------------------|--------------:|
| **client_browser** | The browser is not supported | *unsupported* |
| **fullscreen_change** | Exited fullscreen without completing iProov | *aborted* |
| **ambiguous_outcome** | Sorry, ambiguous outcome | *failed* |
| **network_problem** | Sorry, network problem | *failed* |
| **user_timeout** | Sorry, your session has timed out | *failed* |
| **lighting_flash_reflection_too_low** | Ambient light too strong or screen brightness too low | *failed* |
| **lighting_backlit** | Strong light source detected behind you | *failed* |
| **lighting_too_dark** | Your environment appears too dark | *failed* |
| **lighting_face_too_bright** | Too much light detected on your face | *failed* |
| **motion_too_much_movement** | Please keep still | *failed* |
| **motion_too_much_mouth_movement** | Please do not talk while iProoving | *failed* |
| **client_config** | There was an error with the client configuration | *error* |
| **client_api** | There was an error calling the API | *error* |
| **client_camera** | There was an error getting video from the camera | *error* |
| **client_stream** | There was an error streaming the video | *error* |
| **client_error** | An unknown error occurred | *error* |
| **server_abort** | The server aborted the claim before iProov completed | *error* |

### Listeners

It is recommended that you listen for at least the **ready** and **unsupported** events as one of them will always be called so you can determine if iProov is supported or not:

```javascript
document.querySelector('iproov-me').addEventListener('ready', function(event) {
console.log('iProov is ready to ' + event.detail.type + ' with token ' + event.detail.token);
});
document.querySelector('iproov-me').addEventListener('unsupported', function(event) {
console.warn('iProov is not supported: ' + event.detail.reason);
});
```

> The **unsupported** event will be called by older browsers that supports [CustomEvents](https://caniuse.com/customevent) (browsers released in 2011 and after - e.g. IE9+). If you want to degrade nicely in even older browsers, you should implement you own test like [checking for CustomEvent](https://stackoverflow.com/questions/20956964/detect-working-customevent-constructor).
As all of the event **details** follow the same structure, they can be handled by a single function if desired:

```javascript
var iProovMe = document.querySelector('iproov-me');
iProovMe.addEventListener('ready', iProovEvent);
iProovMe.addEventListener('started', iProovEvent);
iProovMe.addEventListener('aborted', iProovEvent);
iProovMe.addEventListener('streamed', iProovEvent);
iProovMe.addEventListener('progress', iProovEvent);
iProovMe.addEventListener('passed', iProovEvent);
iProovMe.addEventListener('failed', iProovEvent);
iProovMe.addEventListener('error', iProovEvent);
iProovMe.addEventListener('unsupported', iProovEvent);

function iProovEvent(event) {
switch(event.type) {
case 'aborted':
case 'failed':
case 'error':
case 'unsupported':
console.warn('iProov ' + event.type + ' - ' + event.detail.reason);
break;
case 'progress':
console.info(event.detail.message + ' (' + event.detail.percentage + '%)');
break;
default:
console.log('iProov ' + event.detail.type + ' ' + event.type);
}
}
```

If using [jQuery](https://jquery.com), you can attach to all the events in one go:

```javascript
$('iproov-me').on('ready started aborted streamed progress passed failed error unsupported', iProovEvent);
```

Further examples of event usage can be found in [examples.js](./examples.js) and [script.js](./script.js).

## Customisation
Visual customisation can be achieved with [templates and slots](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots) using the [Shadow DOM API](https://webkit.org/blog/4096/introducing-shadow-dom-api/). The following [slots](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) can be used with the iProov Web Component and have associated [events](#events):

| Slot | Description |
|-----------------|------------------------------------------------------------------------------------------------|
| **button** | Element that a user taps or clicks on to launch into fullscreen and start iProov |
| **ready** | Screen displayed to the user when the component is ready to start the main iProov user journey |
| **aborted** | Screen displayed to the user when they exit fullscreen before iProoving |
| **progress** | Screen displayed to the user when streaming has completed and iProov is processing the result |
| **passed** | Screen displayed to the user when the user passed iProov |
| **failed** | Screen displayed to the user when the user failed iProov |
| **error** | Screen displayed to the user in the event of an error |
| **unsupported** | Screen displayed to the user when their browser is not supported |

Slots can be embedded as HTML or injected with JavaScript.

### HTML
The simplest way to add a slot is to include it within the `<iproov-me>` HTML tag:

```html
<iproov-me token="***YOUR_TOKEN_HERE***" type="enrol">
<div slot="ready">
<h1>Register your face</h1>
</div>
<button slot="button">Start face scan...</button>
</iproov-me>
```

> In order to style and manipulate your slots, you can add custom classes and IDs which can be accessed from your CSS and JavaScript.
### JavaScript
You can also build up the slots with JavaScript before injecting the Web Component:

```javascript
window.addEventListener('WebComponentsReady', function(event) {
var component = new IProovMe({
token: '***YOUR_TOKEN_HERE***',
type: 'enrol'
});

var ready = document.createElement('div');
ready.setAttribute('slot', 'ready');
ready.innerHTML = '<h1>Register your face</h1>';
component.appendChild(ready);

var button = document.createElement('button');
button.setAttribute('slot', 'button');
button.innerText = 'Start face scan...';
component.appendChild(button);

document.getElementById('element-id').appendChild(component);
});
```

With [jQuery](https://jquery.com), the entire Web Component can be injected with slots using HTML syntax, for example:

```javascript
window.addEventListener('WebComponentsReady', function(event) {
var component = $('<iproov-me token="***YOUR_TOKEN_HERE***" type="enrol"></iproov-me>');

component.append('<div slot="ready"><h1>Register your face</h1></div>');
component.append('<button slot="button">Start face scan...</button>');

$('#element-id').append(component);
});
```

Further examples of slot usage can be found in the [HTML](./examples/html.html), [JavaScript](./examples/javascript.html) and [jQuery](./examples/jquery.html) examples.
Loading

0 comments on commit 82bfc15

Please sign in to comment.