# DeviceAssure Web Client # The purpose of this JavaScript library is to analyse and validate a device visiting a webpage with the library embedded. The collected data is compared with sets of known valid characteristics for legitimate devices. This comparison and validation is performed by the DeviceAssure backend service. The data collected by the library may be sent to the DeviceAssure service in two ways. ### Client to server model ### The data is sent directly from the client library to the DeviceAssure backend service. Validation results are returned to the library and optionally to a configured callback URL. ### Server to server model ### The data is collected and made available on the client. The DeviceAssure library will not make a request to the DeviceAssure service. It is the responsibility of the calling application to transmit the data to a suitable server and for that server to make the request to the DeviceAssure service. The validation results are returned directly back to the calling server and not to the client application. --- # Data # The library collects data about the underlying hardware and browser capabilities. It does not collect any PII data. The library stores our data in a configurable location to prevent subsequent calls to the DeviceAssure library for a **30 minute** period. DeviceAssure will not be called again until the cache expires or is deleted. It is possible to delete the cached location within our library. The expiry and the location of the cache can be set, or can be disabled entirely. Please see the DeviceAssure Cache Configuration section for more details. --- # Setup # The DeviceAssure JavaScript library must be included on a webpage for it to function. It is recommended to include the library at the end of the web page. This section the setup process for the library for "Client to Server", "Server to Server" and "IMEI Device Check" usages. ## Client to Server usage ## For this option the data is collected by the library and automatically sent to the DeviceAssure service to be analysed. There are two recommended ways to use the library in this scenario. The first is to call the `.check` method directly on an event of some sort e.g. the click of a button and the second is on page load. ### User Event ### The below sample code shows how to include and how to call the DeviceAssure library upon a triggered event. In this example, a user event is shown. A valid licence key _must_ be provided by replacing the placeholder `LICENCE_KEY`. ##### Please Note: ##### Calling the `.check` method on page load is not recommended as it could lead to an invalid device detection due to the DeviceAssure library not having enough time to collect all the required data. It is therefore recommended to only call the `.check` method on a user event such as a button click. This can be seen below: ```html <!-- Library can be imported before this is called --> <script src="<path/to/deviceAssure.min.js>"></script> <!-- Call the check method and handle results --> <script type="text/javascript"> var onSuccess = function (response) { console.log('Handle successful response here.', response); }; var onError = function (error) { console.log('Handle error or failed response here.', error) }; $('.example-submit-button').on('click', function() { DeviceValidation.check('LICENCE_KEY', onSuccess, onError); }); </script> <script src="<path/to/deviceAssure.min.js>"></script> ``` Please see the Implementation Guide for the structure and examples of the returned validation data. A working example can be seen on the `/on-event.html` page. ### Page Load Setup ### Alternatively, if the required behaviour is to only call the DeviceAssure service on page load, only the configuration definition is required. There is no need to call the `check` method, this will be called automatically with the following setup. If there is a cache, the `check` method will return the cached response. If there is no cache, the `check` method will fire off another request. This can be seen below: ```html <!-- Setup the configs. --> <script type="text/javascript"> DeviceValidation = { options: { licence: 'LICENCE_KEY', onSuccess: function(response) { // success callback is optional console.log('Handle successful response here.', response); }, onFailure: function(error) { // failure callback is optional console.log('Handle error or failed response here.', error) } } }; </script> <!-- Note how the configs are defined before the import of the DeviceAssure script --> <script src="<path/to/deviceAssure.min.js>" defer></script> ``` A working example can be seen in on the `/index.html` page. #### Alternative Setup (Vue, Angular, React etc) #### Alternatively, the DeviceValidation library can be declared on the window object. (This can be useful when implementing in a framework such as AngularJS, React or Vue). ```html <!-- Setup our configs. --> <script type="text/javascript"> window.DeviceValidation = { options: { licence: 'LICENCE_KEY', onSuccess: function(response) { // success callback is optional console.log('Handle successful response here.', response); }, onFailure: function(error) { // failure callback is optional console.log('Handle error or failed response here.', error) } } }; </script> <!-- Note how the configs are defined before the import of the DeviceAssure script --> <script src="<path/to/deviceAssure.min.js>" defer></script> ``` The library can to be imported into a js file dynamically and then setup at runtime inside a component. Angular and React will need to do something similar too with loading the library in at runtime. A Vue example component can be seen below: ```vue <template> <div class="deviceassure-component"></div> </template> <script> export default { name: "DeviceAssure", props: { licence: { type: String, default: '<LICENCE_KEY>', }, imei: { type: Boolean, default: false, }, serverToServer: { type: Boolean, default: false, }, onSuccess: { type: Function, default: () => {}, }, onError: { type: Function, default: () => {}, }, // possibly set up more configs here. }, created() { this.loadDeviceAssure(); }, methods: { loadDeviceAssure() { if (window.DeviceValidation && window.DeviceValidation.check) { this.instance = window.DeviceValidation; return; } // Normal setup here window.DeviceValidation = { options: { licence: this.$props.licence, imei: this.$props.imei, serverToServer: this.$props.serverToServer, onSuccess: (data) => { this.response = data; this.$props.onSuccess(data); console.log("onSuccess: ", data); }, onError: (err) => { this.error = err; this.$props.onError(err); console.log("Error: ", err); }, }, }; import("@/libs/dv.min.js").then(() => { if (!this.instance) { this.instance = window.DeviceValidation; console.log("Loaded DeviceAssure", this.instance); } }); }, checkIMEI(imei) { var overridingConfigs = { onSuccess: (data) => { console.log("Check IMEI onSuccess: ", data); }, onError: (err) => { console.log("Check IMEI Error: ", err); }, }; this.instance.checkIMEI(imei, overridingConfigs); }, check() { this.instance.check( this.$props.licence, (data) => { this.response = data; this.$props.onSuccess(data); }, (err) => { this.error = err; this.$props.onError(err); } ); }, getResponse() { return this.response; }, getError() { return this.error; }, }, data() { return { instance: null, response: {}, error: {}, }; } } </script> ```` ## Server to Server usage # In this use-case, the device data is collected by the library and made available to the calling application. It is then the responsibility of the calling application to send the data to an appropriate server that subsequently makes a request to the DeviceAssure service. Please see the Implementation Guide for further details on how to send the data from a server context. Note: A licence key is not required on the client side in this scenario. It must however be provided on the server side before making the request to the DeviceAssure service. The Server to Server functionality may be enabled by adding a **serverToServer: true** parameter to the options object before calling the library. This flag will disable the automatic device validation call to the DeviceAssure service and will instead make the collected data available to the calling application. #### Please Note: #### The serverToServer flag will prevent the automatic trigger of the `check` method. This method can still be called manually and will work as if called in a similar fashion to the Client to Server scenario. The collected data may be retrieved from the library synchronously or asynchronously. Both approaches are shown below: ```html <!-- Enable server to server mode, this will prevent a check request from firing automatically. NOTE: Calling the .check() method will still work as expected and send a request to the DeviceAssure service. The config is only used to prevent the automatic call on page load. --> <script type="text/javascript"> DeviceValidation = { options: { serverToServer: true } }; </script> <!-- Note how the configs are defined before the import of the DeviceAssure script --> <script src="<path/to/deviceAssure.min.js>" type="text/javascript"></script> <!-- call the getData() function --> <script type="text/javascript"> // Asynchronous call by providing a callback function: function callBack(collectedData) { var payload = collectedData; // Proceed with your response or perhaps use our DeviceValidation.check() method above. } // Asynchronous approach DeviceValidation.getData(callBack); // OR alternatively a synchronous blocking call may be made: var payload = DeviceValidation.getData(); </script> ``` A working example can be seen in on the `/indexServer2Server.html` page. ## IMEI Device Check usage # The ability to check if a provided IMEI is lost / stolen and aligns with other identifiers is an optional extra. In this scenario, the data is collected on load of the application, much like the server to sever. However, it does not automatically send API calls without the input of a valid IMEI, so this feature is not suited for automatic validation on page load. But best suited for user interaction. #### Please Note: #### A valid licence key is required for use. The IMEI functionality may be enabled by adding the parameter **imei: true** to the options object before calling the library. This flag will disable the automatic validation to the DeviceAssure service and will only send the call request when the checkIMEI method is called on the library. The collected data can be retrieved from the library asynchronously. See below for an example: ##### Callbacks defined in config ##### ```html <script type="text/javascript"> DeviceValidation = { options: { imei: true, //enable the IMEI api call and prevent call on page load licence: '<LICENCE_KEY>', onSuccess: function(response) { console.log('Handle successful response here.', response); }, onError: function(error) { console.log('Handle error or failed response here.', error) } } }; </script> <!-- Note how the configs are defined before the import of the DeviceAssure script --> <script src="<path/to/deviceAssure.min.js>" type="text/javascript"></script> <script type="text/javascript"> $('.example-submit-button').on('click', function() { DeviceValidation.checkIMEI('<IMEI>'); }); </script> ``` ##### Alternative setup ##### ```html <script type="text/javascript"> DeviceValidation = { options: { imei: true, //enable the IMEI api call and prevent call on page load } }; </script> <!-- Note how the configs are defined before the import of the DeviceAssure script --> <script src="<path/to/deviceAssure.min.js>" type="text/javascript"></script> <script type="text/javascript"> var onSuccess = function(response) { console.log('Handle successful response here.', response); }; var onError = function(error) { console.log('Handle error or failed response here.', error) }; $('.example-submit-button').on('click', function() { var overridingConfigs = { licence: '<LICENCE_KEY>', onSuccess: onSuccess, onError: onError }; DeviceValidation.checkIMEI('<IMEI>', overridingConfigs); }); </script> ``` A working example can be seen in on the `/imei.html` page. --- # DeviceAssure Cache Configuration # Collected device information is stored in the browser inside a cache. It is possible to modify the default behaviour in order to store this information in another type of web-storage. ### Storage Type / Location ### The available options are: ###### `local-storage` - Default ###### Using `local-storage` means DeviceAssure will use localStorage to track whether to call the check endpoint. It stores a JSON string with the time of expiry and the blocking value. ###### `cookie` ###### Using `cookie` means DeviceAssure will use cookies to track whether to call the check endpoint. The expiration of the cookie will indicate whether to make another call or not. ###### `none` ###### Using `none` will never save any response from DeviceAssure. This means that every time the DeviceAssure library is called, it will make a call to the DeviceAssure service. It will also wipe any keys from the cache that were previously added. Please be aware, this could be an expensive option as it will make a call every time the library is loaded. This option is not recommended. If any of these storage options are cleared or expire, then another DeviceAssure call is made. ##### Example setup ###### Below is an example of overriding the storage type to a different value . If the default behaviour is sufficient then no configuration for storageType is required. ```html <!-- Setup our configs. --> <script type="text/javascript"> window.DeviceValidation = { options: { licence: 'LICENCE_KEY', onSuccess: function(response) { // success callback is optional console.log('Handle successful response here.', response); }, onFailure: function(error) { // failure callback is optional console.log('Handle error or failed response here.', error) }, storageType: 'cookie' // cache type to store test results - available options 'cookie', 'local-storage' or 'none } }; </script> <!-- Note how the configs are defined before the import of the DeviceAssure script --> <script src="<path/to/deviceAssure.min.js>" defer></script> ``` #### User event #### ```html <!-- The storageType can be specified in the config --> <script type="application/javascript"> DeviceValidation = { options: { storageType: 'none' // cache type to store test results - available options 'cookie', 'local-storage' or 'none } }; </script> <!-- Library should be imported before this is called --> <script src="<path/to/deviceAssure.min.js>"></script> <!-- Call the check method and handle results --> <script type="text/javascript"> var onSuccess = function (response) { console.log('Handle successful response here.', response); }; var onError = function (error) { console.log('Handle error or failed response here.', error) }; $('.example-submit-button').on('click', function() { DeviceValidation.check('LICENCE_KEY', onSuccess, onError); }); </script> <script src="<path/to/deviceAssure.min.js>"></script> ``` A more in depth example can be seen in the example page found in example/index.html It has a default cache set to `local-storage`. ### DeviceAssure Cache Expiry Configuration ### It is also possible to set the expiry time of the cache. This is the time in milliseconds that the cache will be valid for. The default value is 30 minutes. If the cache expires, then another DeviceAssure call is made. The valid configuration for this property is between 1 millisecond and 24 hours. This is to prevent some unwanted/persisted behaviour. ##### Example setup ###### Below is an example of overriding the storage type to a different value. If the default behaviour is sufficient then no configuration for storageExpiry is required. ```html <!-- Setup our configs. --> <script type="text/javascript"> window.DeviceValidation = { options: { licence: 'LICENCE_KEY', onSuccess: function(response) { // success callback is optional // Handle successful response here. }, onFailure: function(error) { // failure callback is optional // Handle error or failed response here. }, storageExpiry: 8 * 60 * 60 * 1000 // cache expiry time in milliseconds - default is 30 minutes } }; </script> <!-- Note how the configs are defined before the import of the DeviceAssure script --> <script src="<path/to/deviceAssure.min.js>" defer></script> ``` #### User event #### ```html <!-- The storageExpiry can be specified in the config --> <script type="application/javascript"> DeviceValidation = { options: { storageExpiry: 8 * 60 * 60 * 1000 // cache expiry time in milliseconds - default is 30 minutes } }; </script> <!-- Library should be imported before this is called --> <script src="<path/to/deviceAssure.min.js>"></script> <!-- Call the check method and handle results --> <script type="text/javascript"> $('.example-submit-button').on('click', function() { var onSuccess = function (response) { console.log('Handle successful response here.', response); }; var onError = function (error) { console.log('Handle error or failed response here.', error) }; DeviceValidation.check('LICENCE_KEY', onSuccess, onError); }); </script> <script src="<path/to/deviceAssure.min.js>"></script> ``` --- ## DeviceAssure Configurations ### The following is a list of configurations that can be set on the DeviceAssure library. | Property | Type | Default | Description | |------------------|----------|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| | `serverToServer` | Boolean | `false` | Enable server to server mode. This will disable the automatic validation to the DeviceAssure service and manual data collection can then occur via `getData`. | | `imei` | Boolean | `false` | Enable IMEI mode. This will disable the automatic validation to the DeviceAssure service and manual calling of the `checkIMEI` method is required. | | `licence` | String | `null` | The licence key to use for the DeviceAssure service. Required for Client to Server usage. | | `onSuccess` | Function | `function() {}` | The callback function to call when the DeviceAssure service returns a successful response. | | `onError` | Function | `function() {}` | The callback function to call when the DeviceAssure service returns an error response. | | `storageType` | String | `local-storage` | The type of storage to use for the DeviceAssure cache. Available options are `local-storage`, `cookie` or `none`. | | `storageExpiry` | Number | `1800000` | The time in milliseconds that the DeviceAssure cache will be valid for. The minimum value is 1 millisecond and the maximum value is 24 hours. | ### DeviceAssure Methods ### The following is a list of methods in the library. | Property | Description | |--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `check` | Will hit the DeviceAssure Cloud API, it will not send if there's no correct licence. | | `checkIMEI` | Will hit the DeviceAssure Cloud API and verify the TAC supplied is valid for the device, it will not send if there's no correct licence or missing TAC. | | `getData` | Returns the payload with the dataCollectorKey and serverToServer property turned on. It should only be used with serverToServer turned on, it does not send any requests. | ### Reference ### ```javascript DeviceValidation = { options: { serverToServer: true, //enable the server to server api call and prevent call on page load imei: true, //enable the IMEI api call and prevent call on page load licence: '<LICENCE_KEY>', storageType: 'cookie', // available options 'cookie', 'local-storage' or 'none storageExpiry: 8 * 60 * 60 * 1000, // overriding to 8 hours onSuccess: function(response) { console.log('Handle successful response here.', response); }, onError: function(error) { console.log('Handle error or failed response here.', error) } } }; ``` --- ## Sample Application ## A sample application is included in the package. This sample shows usage for both above examples. - Client to Server (On Page Load) - Client to Server (On User Event) - Server to Server - IMEI Check A valid DeviceAssure licence key is required for the "Client to Server" and IMEI Check examples. ## Copyright ## Copyright (c) DeviceAtlas Limited 2023. All rights reserved. https://deviceatlas.com