UNPKG

web-pki

Version:

The Lacuna Web PKI component enables web applications to interact with digital certificates through javascript, without the need of Java.

1,534 lines (1,361 loc) 104 kB
// -------------------- Add-on placeholder (IE only) -------------------- if (typeof window.lacunaWebPKIExtension === 'undefined') { window.lacunaWebPKIExtension = null; } // -------------------- Class declaration -------------------- window.LacunaWebPKI = null; LacunaWebPKI = function (license) { this.license = null; this.defaultFailCallback = null; this.angularScope = null; this.ngZone = null; this.brand = null; this.restPkiUrl = null; this.useDomainNativePool = false; this.mobileIntegrationMode = null; if (license) { this.license = license; } // check for JQuery blockUI presence causing mobile touch blocking if (this.isSupportedMobile && window.$ && window.$.blockUI) { try { window.$.blockUI.defaults.bindEvents = false; this._log('blockUI bindEvents disabled'); } catch (ex) { this._log('Error disabling blockUI bindEvents: ', ex); } } }; // Inject class prototype (function ($) { // -------------------- Promise subclass -------------------- $.Promise = function (angularScope, ngZone) { this.successCallback = function() { }; this.failCallback = null; this.angularScope = angularScope; this.ngZone = ngZone; }; $.Promise.prototype.success = function (callback) { this.successCallback = callback; return this; }; $.Promise.prototype.error = function (callback) { // for backward compatibility, any legacy error callback converted to a fail callback this.failCallback = function(ex) { callback(ex.message, ex.error, ex.origin, ex.code); }; return this; }; $.Promise.prototype.fail = function (callback) { this.failCallback = callback; return this; }; $.Promise.prototype._invokeSuccess = function (result, delay) { if (delay > 0) { var self = this; setTimeout(function () { self._invokeSuccess(result); }, delay); } else { var callback = this.successCallback || function () { $._log('Success ignored (no callback registered)'); }; this._apply(function () { callback(result); }); } }; $.Promise.prototype._invokeError = function (ex, delay) { if (delay > 0) { var self = this; setTimeout(function () { self._invokeError(ex); }, delay); } else { var callback = this.failCallback || function (ex) { throw 'Web PKI error originated at ' + ex.origin + ': ' + ex.message + '\n' + ex.complete + '\ncode: ' + ex.code; }; this._apply(function () { callback({ userMessage: ex.userMessage || ex.message, message: ex.message, error: ex.complete, origin: ex.origin, code: ex.code }); }); } }; // https://coderwall.com/p/ngisma/safe-apply-in-angular-js $.Promise.prototype._apply = function (callback) { if (this.angularScope) { var phase = this.angularScope.$root.$$phase; if (phase == '$apply' || phase == '$digest') { callback(); } else { this.angularScope.$apply(function () { callback(); }); } } else if (this.ngZone) { this.ngZone.run(function () { callback(); }); } else { callback(); } }; // -------------------- Constants -------------------- $._installUrl = 'https://get.webpkiplugin.com/'; $._chromeExtensionId = 'dcngeagmmhegagicpcmpinaoklddcgon'; $._firefoxExtensionId = 'webpki-beta@lacunasoftware.com'; $._edgeExtensionId = 'nedeegdmhlnmboboahchfpkmdnnemapd'; $._edgeLegacyProductId = 'd2798a85-9698-425a-add7-3db79a39ca8a'; $._chromeExtensionFirstVersionWithSelfUpdate = '2.0.20'; $._jslibVersion = '2.18.0'; $._mobileSupported = 'true' === 'true'; $._buildChannel = 'stable'; // latest components version ---------------------- $._extensionRequiredVersion = '1.0.0'; $._chromeNativeWinRequiredVersion = '2.14.0'; $._chromeNativeLinuxRequiredVersion = '2.14.0'; $._chromeNativeMacRequiredVersion = '2.14.0'; $._ieAddonRequiredVersion = '2.9.1'; $._mobileRequiredVersion = '3.2.0'; // ------------------------------------------------ $._chromeInstallationStates = { INSTALLED: 0, EXTENSION_NOT_INSTALLED: 1, EXTENSION_OUTDATED: 2, NATIVE_NOT_INSTALLED: 3, NATIVE_OUTDATED: 4 }; $._certKeyUsages = { crlSign: 2, dataEncipherment: 16, decipherOnly: 32768, digitalSignature: 128, encipherOnly: 1, keyAgreement: 8, keyCertSign: 4, keyEncipherment: 32, nonRepudiation: 64 }; $._certExtendedKeyUsages = { clientAuth: 1, serverAuth: 2, codeSigning: 4, emailProtection: 8, timeStamping: 16, ocspSigning: 32, ipsecEndSystem: 64, ipsecTunnel: 128, ipsecUser: 256, any: 512 }; $.apiVersions = { v1_0: '1.0', v1_1: '1.1', v1_2: '1.2', v1_3: '1.3', v1_4: '1.4', v1_4_1: '1.4.1', v1_5: '1.5', v1_5_1: '1.5.1', v1_5_2: '1.5.2', v1_6: '1.6.0', v1_6_1: '1.6.1', v1_7_0: '1.7.0', v1_7_2: '1.7.2', v1_8_0: '1.8.0', v1_8_1: '1.8.1', v1_8_2: '1.8.2', v1_8_3: '1.8.3', v1_8_4: '1.8.4', v1_8_5: '1.8.5', v1_8_6: '1.8.6', v1_9_0: '1.9.0', latest: 'latest' }; $._apiMap = { nativeWin: {}, nativeLinux: {}, nativeMac: {}, ieAddon: {}, extension: {}, mobile: {} }; // syntax: api_version: supported_since_version // Windows $._apiMap.nativeWin[$.apiVersions.v1_0] = '2.1.0'; $._apiMap.nativeWin[$.apiVersions.v1_1] = '2.3.0'; $._apiMap.nativeWin[$.apiVersions.v1_2] = '2.4.1'; $._apiMap.nativeWin[$.apiVersions.v1_3] = '2.5.0'; $._apiMap.nativeWin[$.apiVersions.v1_4] = '2.6.2'; $._apiMap.nativeWin[$.apiVersions.v1_4_1] = '2.6.5'; $._apiMap.nativeWin[$.apiVersions.v1_5] = '2.8.0'; $._apiMap.nativeWin[$.apiVersions.v1_5_1] = '2.8.1'; $._apiMap.nativeWin[$.apiVersions.v1_5_2] = '2.9.0'; $._apiMap.nativeWin[$.apiVersions.v1_6] = '2.10.0'; $._apiMap.nativeWin[$.apiVersions.v1_6_1] = '2.10.1'; $._apiMap.nativeWin[$.apiVersions.v1_7_0] = '2.11.0'; $._apiMap.nativeWin[$.apiVersions.v1_7_2] = '2.11.0'; $._apiMap.nativeWin[$.apiVersions.v1_8_0] = '2.12.0'; $._apiMap.nativeWin[$.apiVersions.v1_8_1] = '2.12.1'; $._apiMap.nativeWin[$.apiVersions.v1_8_2] = '2.12.3'; $._apiMap.nativeWin[$.apiVersions.v1_8_3] = '2.12.6'; $._apiMap.nativeWin[$.apiVersions.v1_8_4] = '2.12.7'; $._apiMap.nativeWin[$.apiVersions.v1_8_5] = '2.13.2'; $._apiMap.nativeWin[$.apiVersions.v1_8_6] = '2.14.0'; $._apiMap.nativeWin[$.apiVersions.v1_9_0] = '2.12.3'; // IE $._apiMap.ieAddon[$.apiVersions.v1_0] = '2.0.4'; $._apiMap.ieAddon[$.apiVersions.v1_1] = '2.1.1'; $._apiMap.ieAddon[$.apiVersions.v1_2] = '2.2.4'; $._apiMap.ieAddon[$.apiVersions.v1_3] = '2.3.0'; $._apiMap.ieAddon[$.apiVersions.v1_4] = '2.4.2'; $._apiMap.ieAddon[$.apiVersions.v1_4_1] = '2.4.5'; $._apiMap.ieAddon[$.apiVersions.v1_5] = '2.5.0'; $._apiMap.ieAddon[$.apiVersions.v1_5_1] = '2.5.2'; $._apiMap.ieAddon[$.apiVersions.v1_5_2] = '2.6.0'; $._apiMap.ieAddon[$.apiVersions.v1_6] = '2.7.0'; $._apiMap.ieAddon[$.apiVersions.v1_6_1] = '2.7.2'; $._apiMap.ieAddon[$.apiVersions.v1_7_0] = '2.8.0'; $._apiMap.ieAddon[$.apiVersions.v1_7_2] = '2.8.0'; $._apiMap.ieAddon[$.apiVersions.v1_8_0] = '2.9.0'; $._apiMap.ieAddon[$.apiVersions.v1_8_1] = '2.9.1'; $._apiMap.ieAddon[$.apiVersions.v1_8_2] = '2.9.1'; $._apiMap.ieAddon[$.apiVersions.v1_8_3] = '2.9.1'; $._apiMap.ieAddon[$.apiVersions.v1_8_4] = '2.9.1'; $._apiMap.ieAddon[$.apiVersions.v1_8_5] = '2.9.1'; $._apiMap.ieAddon[$.apiVersions.v1_8_6] = '2.9.1'; $._apiMap.ieAddon[$.apiVersions.v1_9_0] = '2.9.1'; // Linux $._apiMap.nativeLinux[$.apiVersions.v1_0] = '2.0.0'; $._apiMap.nativeLinux[$.apiVersions.v1_1] = '2.4.0'; $._apiMap.nativeLinux[$.apiVersions.v1_2] = '2.6.2'; $._apiMap.nativeLinux[$.apiVersions.v1_3] = '2.7.0'; $._apiMap.nativeLinux[$.apiVersions.v1_4] = '2.7.4'; $._apiMap.nativeLinux[$.apiVersions.v1_4_1] = '2.7.4'; $._apiMap.nativeLinux[$.apiVersions.v1_5] = '2.9.0'; $._apiMap.nativeLinux[$.apiVersions.v1_5_1] = '2.9.0'; $._apiMap.nativeLinux[$.apiVersions.v1_5_2] = '2.9.5'; $._apiMap.nativeLinux[$.apiVersions.v1_6] = '2.10.0'; $._apiMap.nativeLinux[$.apiVersions.v1_6_1] = '2.10.0'; $._apiMap.nativeLinux[$.apiVersions.v1_7_0] = '2.12.0'; $._apiMap.nativeLinux[$.apiVersions.v1_7_2] = '2.12.1'; $._apiMap.nativeLinux[$.apiVersions.v1_8_0] = '2.13.0'; $._apiMap.nativeLinux[$.apiVersions.v1_8_1] = '2.13.1'; $._apiMap.nativeLinux[$.apiVersions.v1_8_2] = '2.13.3'; $._apiMap.nativeLinux[$.apiVersions.v1_8_3] = '2.13.3'; $._apiMap.nativeLinux[$.apiVersions.v1_8_4] = '2.13.3'; $._apiMap.nativeLinux[$.apiVersions.v1_8_5] = '2.13.3'; $._apiMap.nativeLinux[$.apiVersions.v1_8_6] = '2.14.0'; $._apiMap.nativeLinux[$.apiVersions.v1_9_0] = '2.13.3'; // Mac $._apiMap.nativeMac[$.apiVersions.v1_0] = '2.3.0'; $._apiMap.nativeMac[$.apiVersions.v1_1] = '2.4.0'; $._apiMap.nativeMac[$.apiVersions.v1_2] = '2.6.1'; $._apiMap.nativeMac[$.apiVersions.v1_3] = '2.7.0'; $._apiMap.nativeMac[$.apiVersions.v1_4] = '2.7.4'; $._apiMap.nativeMac[$.apiVersions.v1_4_1] = '2.7.4'; $._apiMap.nativeMac[$.apiVersions.v1_5] = '2.9.0'; $._apiMap.nativeMac[$.apiVersions.v1_5_1] = '2.9.0'; $._apiMap.nativeMac[$.apiVersions.v1_5_2] = '2.9.5'; $._apiMap.nativeMac[$.apiVersions.v1_6] = '2.10.0'; $._apiMap.nativeMac[$.apiVersions.v1_6_1] = '2.10.0'; $._apiMap.nativeMac[$.apiVersions.v1_7_0] = '2.12.0'; $._apiMap.nativeMac[$.apiVersions.v1_7_2] = '2.12.1'; $._apiMap.nativeMac[$.apiVersions.v1_8_0] = '2.13.0'; $._apiMap.nativeMac[$.apiVersions.v1_8_1] = '2.13.1'; $._apiMap.nativeMac[$.apiVersions.v1_8_2] = '2.13.3'; $._apiMap.nativeMac[$.apiVersions.v1_8_3] = '2.13.5'; $._apiMap.nativeMac[$.apiVersions.v1_8_4] = '2.13.5'; $._apiMap.nativeMac[$.apiVersions.v1_8_5] = '2.13.5'; $._apiMap.nativeMac[$.apiVersions.v1_8_6] = '2.14.0'; $._apiMap.nativeMac[$.apiVersions.v1_9_0] = '2.13.3'; // WebExtension $._apiMap.extension[$.apiVersions.v1_0] = '2.3.2'; $._apiMap.extension[$.apiVersions.v1_1] = '2.7.0'; $._apiMap.extension[$.apiVersions.v1_2] = '2.9.1'; $._apiMap.extension[$.apiVersions.v1_3] = '2.10.1'; $._apiMap.extension[$.apiVersions.v1_4] = '2.11.7'; $._apiMap.extension[$.apiVersions.v1_4_1] = '2.11.7'; $._apiMap.extension[$.apiVersions.v1_5] = '2.13.0'; $._apiMap.extension[$.apiVersions.v1_5_1] = '2.13.0'; $._apiMap.extension[$.apiVersions.v1_5_2] = '2.14.2'; $._apiMap.extension[$.apiVersions.v1_6] = '2.15.0'; $._apiMap.extension[$.apiVersions.v1_6_1] = '2.15.0'; $._apiMap.extension[$.apiVersions.v1_7_0] = '2.16.0'; $._apiMap.extension[$.apiVersions.v1_7_2] = '2.16.0'; $._apiMap.extension[$.apiVersions.v1_8_0] = '2.16.0'; $._apiMap.extension[$.apiVersions.v1_8_1] = '2.16.0'; $._apiMap.extension[$.apiVersions.v1_8_2] = '2.16.0'; $._apiMap.extension[$.apiVersions.v1_8_3] = '2.16.0'; $._apiMap.extension[$.apiVersions.v1_8_4] = '2.16.0'; $._apiMap.extension[$.apiVersions.v1_8_5] = '2.16.0'; $._apiMap.extension[$.apiVersions.v1_8_6] = '2.16.0'; $._apiMap.extension[$.apiVersions.v1_9_0] = '2.17.0'; // Mobile $._apiMap.mobile[$.apiVersions.v1_0] = '1.1.0'; $._apiMap.mobile[$.apiVersions.v1_1] = '1.1.0'; $._apiMap.mobile[$.apiVersions.v1_2] = '1.1.0'; $._apiMap.mobile[$.apiVersions.v1_3] = '1.1.0'; $._apiMap.mobile[$.apiVersions.v1_4] = '1.1.0'; $._apiMap.mobile[$.apiVersions.v1_4_1] = '1.1.0'; $._apiMap.mobile[$.apiVersions.v1_5] = '1.1.0'; $._apiMap.mobile[$.apiVersions.v1_5_1] = '1.1.0'; $._apiMap.mobile[$.apiVersions.v1_5_2] = '1.1.0'; $._apiMap.mobile[$.apiVersions.v1_6] = '2.7.0'; $._apiMap.mobile[$.apiVersions.v1_6_1] = '2.7.0'; $._apiMap.mobile[$.apiVersions.v1_7_0] = '3.0.0'; $._apiMap.mobile[$.apiVersions.v1_7_2] = '3.0.0'; $._apiMap.mobile[$.apiVersions.v1_8_0] = '3.2.0'; $._apiMap.mobile[$.apiVersions.v1_8_1] = '3.2.0'; $._apiMap.mobile[$.apiVersions.v1_8_2] = '3.2.0'; $._apiMap.mobile[$.apiVersions.v1_8_3] = '3.2.0'; $._apiMap.mobile[$.apiVersions.v1_8_4] = '3.2.0'; $._apiMap.mobile[$.apiVersions.v1_8_5] = '3.2.0'; $._apiMap.mobile[$.apiVersions.v1_8_6] = '3.2.0'; $._apiMap.mobile[$.apiVersions.v1_9_0] = '3.2.0'; // All latest $._apiMap.nativeWin [$.apiVersions.latest] = $._chromeNativeWinRequiredVersion; $._apiMap.ieAddon [$.apiVersions.latest] = $._ieAddonRequiredVersion; $._apiMap.nativeLinux[$.apiVersions.latest] = $._chromeNativeLinuxRequiredVersion; $._apiMap.nativeMac [$.apiVersions.latest] = $._chromeNativeMacRequiredVersion; $._apiMap.extension [$.apiVersions.latest] = $._extensionRequiredVersion; $._apiMap.mobile [$.apiVersions.latest] = $._mobileRequiredVersion; // populated after init $._nativeInfo = {}; $.installationStates = { INSTALLED: 0, NOT_INSTALLED: 1, OUTDATED: 2, BROWSER_NOT_SUPPORTED: 3 }; // Porperties ----------------------- $.isSupportedMobile = undefined; // Pki Options ---------------------- $.certificateValidationLevels = { full: 'full', offline: 'offline' }; $.padesPolicies = { basic: 'basic', brazilAdrBasica: 'brazilAdrBasica' }; $.cadesPolicies = { bes: 'cadesBes', brazilAdrBasica: 'brazilAdrBasica' }; $.xmlPolicies = { xmlDSig: 'xmlDSig', xadesBes: 'xadesBes', brazilNFe: 'brazilNFe', brazilAdrBasica: 'brazilAdrBasica' }; $.cadesAcceptablePolicies = { pkiBrazil: [ 'brazilAdrBasica', 'brazilAdrTempo', 'brazilAdrValidacao', 'brazilAdrCompleta', 'brazilAdrArquivamento' ] }; $.xmlAcceptablePolicies = { pkiBrazil: [ 'brazilAdrBasica', 'brazilAdrTempo' ] }; $.standardTrustArbitrators = { pkiBrazil: { type: 'standard', standardArbitrator: 'pkiBrazil' }, pkiItaly: { type: 'standard', standardArbitrator: 'pkiItaly' }, pkiPeru: { type: 'standard', standardArbitrator: 'pkiPeru' }, windows: { type: 'standard', standardArbitrator: 'windows' } }; $.xmlInsertionOptions = { appendChild: 'appendChild', prependChild: 'prependChild', appendSibling: 'appendSibling', prependSibling: 'prependSibling' }; $.outputModes = { showSaveFileDialog: 'showSaveFileDialog', saveInFolder: 'saveInFolder', autoSave: 'autoSave', returnContent: 'returnContent' }; $.trustArbitratorTypes = { trustedRoot: 'trustedRoot', tsl: 'tsl', standard: 'standard' }; // visual representation $.padesPaperSizes = { custom: 'custom', a0: 'a0', a1: 'a1', a2: 'a2', a3: 'a3', a4: 'a4', a5: 'a5', a6: 'a6', a7: 'a7', a8: 'a8', letter: 'letter', legal: 'legal', ledger: 'ledger' }; $.padesHorizontalAlign = { left: 'left', center: 'center', rigth: 'rigth' }; $.padesVerticalAlign = { top: 'top', center: 'center', bottom: 'bottom' }; $.padesMeasurementUnits = { centimeters: 'centimeters', pdfPoints: 'pdfPoints' }; $.padesPageOrientations = { auto: 'auto', portrait: 'portrait', landscape: 'landscape' }; $.padesAutoPositioningHorizontalDirections = { leftToRight: 'leftToRight', rightToLeft: 'rightToLeft' }; $.padesAutoPositioningVerticalDirections = { topDown: 'topDown', bottomUp: 'bottomUp' }; // pdf mark $.markElementTypes = { text: 'text', image: 'image' }; $.markTextStyle = { normal: 0, bold: 1, italic: 2 }; // password policies $.passwordPolicies = { lettersAndNumbers: 1, upperAndLowerCase: 2, specialCharacters: 4 }; // standard pkcs11 modules $.pkcs11Modules = { safeSign: { win: 'aetpkss1.dll', linux: 'libaetpkss.so.3', mac: 'libaetpkss.dylib' }, safeNet: { win: 'eTPKCS11.dll', linux: 'libeToken.so', mac: 'libeToken.dylib' } }; $.mobileIntegrationModes = { appIntegration: 'appIntegration', browserIntegration: 'browserIntegration' }; $.encryptionParameters = { rsaEncryptionPkcs1: 'RSAEncryptionPkcs1', rsaEncryptionOaepSHA1: 'RSAEncryptionOaepSHA1', rsaEncryptionOaepSHA256: 'RSAEncryptionOaepSHA256', rsaEncryptionOaepSHA384: 'RSAEncryptionOaepSHA384', rsaEncryptionOaepSHA512: 'RSAEncryptionOaepSHA512' }; $._parseDataUrl = function (url) { var match = /^data:(.+);base64,(.+)$/.exec(url); if (!match) { $._log('failed to parse data url'); return null; } return { mimeType: match[1], content: match[2] }; }; $._downloadResource = function (url, callBack) { $._log('resolving resource reference: ' + url); var xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = 'blob'; xhr.onload = function () { var responseReader = new FileReader(); responseReader.onloadend = function () { $._log('resource reference resolved'); var resource = $._parseDataUrl(responseReader.result); callBack(resource); }; responseReader.readAsDataURL(xhr.response); }; xhr.send(); }; $._getRequestOsP11Modules = function (p11Modules) { if (!p11Modules || !p11Modules.length) { return null; } var osModules = []; for (var i = 0; i < p11Modules.length; i++) { if ($._nativeInfo.os === 'Windows') { osModules.push(p11Modules[i].win); } else if ($._nativeInfo.os === 'Linux') { osModules.push(p11Modules[i].linux); } else if ($._nativeInfo.os === 'Darwin') { osModules.push(p11Modules[i].mac); } } return osModules; }; $._handleP11ModulesArgs = function (args, request) { var p11Modules = null; var tokenSerialNumber = null; if (args.token && typeof args.token === 'object') { p11Modules = [ args.token.pkcs11Module ]; tokenSerialNumber = args.token.serialNumber; } request.pkcs11Modules = p11Modules || request.pkcs11Modules; request.tokenSerialNumber = tokenSerialNumber || request.tokenSerialNumber; }; // WebPKI errors $.errorCodes = { UNDEFINED: 'undefined', INTERNAL: 'internal', USER_CANCELLED: 'user_cancelled', OS_NOT_SUPPORTED: 'os_not_supported', ADDON_TIMEOUT: 'addon_timeout', ADDON_NOT_DETECTED: 'addon_not_detected', ADDON_SEND_COMMAND_FAILURE: 'addon_send_command_failure', CERTIFICATE_NOT_FOUND: 'certificate_not_found', COMMAND_UNKNOWN: 'command_unknown', COMMAND_NOT_SUPPORTED: 'command_not_supported', COMMAND_PARAMETER_NOT_SET: 'command_parameter_not_set', COMMAND_INVALID_PARAMETER: 'command_invalid_parameter', COMMAND_PARAMETER_NOT_SUPPORTED:'command_parameter_not_supported', NATIVE_CONNECT_FAILURE: 'native_connect_failure', NATIVE_DISCONNECTED: 'native_disconnected', NATIVE_NO_RESPONSE: 'native_no_response', REST_PKI_GET_PENDING_SIGNATURE: 'rest_pki_get_pending_signature', REST_PKI_POST_SIGNATURE: 'rest_pki_post_signature', REST_PKI_INVALID_CERTIFICATE: 'rest_pki_invalid_certificate', LICENSE_NOT_SET: 'license_not_set', LICENSE_INVALID: 'license_invalid', LICENSE_RESTRICTED: 'license_restricted', LICENSE_EXPIRED: 'license_expired', LICENSE_DOMAIN_NOT_ALLOWED: 'license_domain_not_allowed', VALIDATION_ERROR: 'validation_error', P11_ERROR: 'p11_error', P11_TOKEN_NOT_FOUND: 'p11_token_not_found', P11_NOT_SUPPORTED: 'p11_not_supported', KEYSET_NOT_FOUND: 'keyset_not_found', ALGORITHM_NOT_SUPPORTED: 'algorithm_not_supported', SIGNED_PDF_TO_MARK: 'signed_pdf_to_mark', JSON_ERROR: 'json_error', IO_ERROR: 'io_error', KEYCHAIN_ERROR: 'keychain_error', KEYCHAIN_SIGN_ERROR: 'keychain_sign_error', DECODE_ERROR: 'decode_error', CSP_KEYSET_NOT_DEFINED: 'csp_keyset_not_defined', CSP_INVALID_ALGORITHM: 'csp_invalid_algorithm', CSP_INVALID_PROVIDER_TYPE: 'csp_invalid_provider_type', MOBILE_TIMEOUT: 'mobile_timeout', MOBILE_NOT_AUTHORIZED: 'mobile_not_authorized', MOBILE_SEND_MESSAGE: 'mobile_send_message', COMMAND_DECRYPT_ERROR: 'command_decrypt_error', BLOCKED_DOMAIN: 'blocked_domain', INVALID_OPERATION: 'invalid_operation' }; // -------------------- "Private" static functions (no reference to 'this') -------------------- $._compareVersions = function (v1, v2) { var v1parts = v1.split('.'); var v2parts = v2.split('.'); function isPositiveInteger(x) { return /^\d+$/.test(x); } function validateParts(parts) { for (var i = 0; i < parts.length; ++i) { if (!isPositiveInteger(parts[i])) { return false; } } return true; } if (!validateParts(v1parts) || !validateParts(v2parts)) { return NaN; } for (var i = 0; i < v1parts.length; ++i) { if (v2parts.length === i) { return 1; } var v1p = parseInt(v1parts[i], 10); var v2p = parseInt(v2parts[i], 10); if (v1p === v2p) { continue; } if (v1p > v2p) { return 1; } return -1; } if (v1parts.length != v2parts.length) { return -1; } return 0; }; $._log = function (message, data) { if (window.console) { if (data) { window.console.log(message, data); } else { window.console.log(message); } } }; // -------------------- "Private" instance functions (with references to 'this') -------------------- $._createContext = function (args) { var promise = new $.Promise(this.angularScope, this.ngZone); if (args && args.success) { promise.success(args.success); } if (args && args.fail) { promise.fail(args.fail); } else if (args && args.error) { promise.error(args.error); } else { promise.fail(this.defaultFailCallback); } var context = { promise: promise, license: this.license, useDomainNativePool: this.useDomainNativePool, instance: $._supportedMobileDetected ? this : undefined }; return context; }; // -------------------- Public functions -------------------- $.init = function (args) { if (!args) { args = {}; } else if (typeof args === 'function') { args = { ready: args }; } if (args.license) { this.license = args.license; } if (args.defaultError) { this.defaultFailCallback = function (ex) { args.defaultError(ex.message, ex.error, ex.origin, ex.code); }; } if (args.defaultFail) { // overwrite any legacy error callback this.defaultFailCallback = args.defaultFail; } if (args.angularScope) { this.angularScope = args.angularScope; } if (args.ngZone) { this.ngZone = args.ngZone; } if (args.brand) { this.brand = args.brand; } if (args.restPkiUrl) { this.restPkiUrl = args.restPkiUrl[args.restPkiUrl.length - 1] === '/' ? args.restPkiUrl : args.restPkiUrl + '/'; } this.useDomainNativePool = args.useDomainNativePool === true; var self = this; var onCheckInstalledSuccess = function (result) { if (result.isInstalled) { if (args.ready) { args.ready(); } else { $._log('Web PKI ready (no callback registered)'); } } else { if (args.notInstalled) { args.notInstalled(result.status, result.message, result.browserSpecificStatus); } else { self.redirectToInstallPage(); } } }; var context = this._createContext({ success: onCheckInstalledSuccess, fail: args.fail, error: args.error }); $._requestHandler.checkInstalled(context, args.requiredApiVersion); return context.promise; }; $.getVersion = function (args) { var context = this._createContext(args); $._requestHandler.sendCommand(context, 'getVersion', null); return context.promise; }; $.listCertificates = function (args) { if (!args) { args = {}; } else if (args.filter) { if (typeof args.filter !== 'function') { if (typeof args.filter === 'boolean') { throw 'args.filter must be a function (hint: if you used "pki.filters.xxx()", try removing the "()")'; } else { throw 'args.filter must be a function, received ' + (typeof args.filter); } } } var context = this._createContext(args); $._requestHandler.sendCommand(context, 'listCertificates', null, function (result) { return $._processCertificates(result, args.filter, args.selectId, args.selectOptionFormatter); }); return context.promise; }; $._processCertificate = function (cert) { cert.validityStart = new Date(cert.validityStart); cert.validityEnd = new Date(cert.validityEnd); cert.keyUsage = $._processKeyUsage(cert.keyUsage); cert.extendedKeyUsage = $._processExtendedKeyUsage(cert.extendedKeyUsage); if (cert.pkiBrazil && cert.pkiBrazil.dateOfBirth) { var s = cert.pkiBrazil.dateOfBirth; cert.pkiBrazil.dateOfBirth = new Date(parseInt(s.slice(0, 4), 10), parseInt(s.slice(5, 7), 10) - 1, parseInt(s.slice(8, 10), 10)); } }; $._processCertificates = function (result, filter, selectId, selectOptionFormatter) { var toReturn = []; for (var i = 0; i < result.length; i++) { var cert = result[i]; $._processCertificate(cert); if (filter) { if (filter(cert)) { toReturn.push(cert); } } else { toReturn.push(cert); } } toReturn.sort(function(a, b) { // sort the certificates by its subject common name (case insensitive) var aName = a.subjectName; var bName = b.subjectName; if (!aName || !bName) { return !aName && bName ? 1 : -1; } aName = aName.toLowerCase(); bName = bName.toLowerCase(); if (aName > bName) { return 1; } else if (aName < bName) { return -1; } else { // same common name, sort by the expiration date, the longer date, the first return a.validityEnd > b.validityEnd ? -1 : (a.validityEnd < b.validityEnd ? 1 : 0); } }); if (selectId) { if (!selectOptionFormatter) { selectOptionFormatter = function (c) { return c.subjectName + ' (issued by ' + c.issuerName + ')'; }; } var select = document.getElementById(selectId); while (select.options.length > 0) { select.remove(0); } for (var j = 0; j < toReturn.length; j++) { var c = toReturn[j]; var option = document.createElement('option'); option.value = c.thumbprint; option.text = selectOptionFormatter(c); select.add(option); } } return toReturn; }; $._processKeyUsage = function (keyUsageValue) { return { crlSign: (keyUsageValue & $._certKeyUsages.crlSign) !== 0, dataEncipherment: (keyUsageValue & $._certKeyUsages.dataEncipherment) !== 0, decipherOnly: (keyUsageValue & $._certKeyUsages.decipherOnly) !== 0, digitalSignature: (keyUsageValue & $._certKeyUsages.digitalSignature) !== 0, encipherOnly: (keyUsageValue & $._certKeyUsages.encipherOnly) !== 0, keyAgreement: (keyUsageValue & $._certKeyUsages.keyAgreement) !== 0, keyCertSign: (keyUsageValue & $._certKeyUsages.keyCertSign) !== 0, keyEncipherment: (keyUsageValue & $._certKeyUsages.keyEncipherment) !== 0, nonRepudiation: (keyUsageValue & $._certKeyUsages.nonRepudiation) !== 0 }; }; $._processExtendedKeyUsage = function (extendedKeyUsageValue) { if (typeof extendedKeyUsageValue !== 'number') { return null; } return { clientAuth: (extendedKeyUsageValue & $._certExtendedKeyUsages.clientAuth) !== 0, serverAuth: (extendedKeyUsageValue & $._certExtendedKeyUsages.serverAuth) !== 0, codeSigning: (extendedKeyUsageValue & $._certExtendedKeyUsages.codeSigning) !== 0, emailProtection: (extendedKeyUsageValue & $._certExtendedKeyUsages.emailProtection) !== 0, timeStamping: (extendedKeyUsageValue & $._certExtendedKeyUsages.timeStamping) !== 0, ocspSigning: (extendedKeyUsageValue & $._certExtendedKeyUsages.ocspSigning) !== 0, ipsecEndSystem: (extendedKeyUsageValue & $._certExtendedKeyUsages.ipsecEndSystem) !== 0, ipsecTunnel: (extendedKeyUsageValue & $._certExtendedKeyUsages.ipsecTunnel) !== 0, ipsecUser: (extendedKeyUsageValue & $._certExtendedKeyUsages.ipsecUser) !== 0, any: (extendedKeyUsageValue & $._certExtendedKeyUsages.any) !== 0 }; }; $._processSignResult = function (result) { if (!result || !result.signatureInfo) { return result; } if (result.signatureInfo.signerCertificate) { $._processCertificate(result.signatureInfo.signerCertificate); } if (result.signatureInfo.signingTime) { result.signatureInfo.signingTime = new Date(result.signatureInfo.signingTime); } return result; }; $._processSignerModel = function (signer) { if (!signer) { return; } if (signer.certificate) { $._processCertificate(signer.certificate); } if (signer.signingTime) { signer.signingTime = new Date(signer.signingTime); } if (signer.certifiedDateReference) { signer.certifiedDateReference = new Date(signer.certifiedDateReference); } if (signer.timestamps && signer.timestamps.length > 0) { for (var i = 0; i < signer.timestamps.length; i++) { var tst = signer.timestamps[i]; $._processOpenResult(tst); } } }; $._processOpenResult = function (result) { if (!result || !result.signers || result.signers.length <= 0) { return result; } // case is a CadesTimestampModel if (result.genTime) { result.genTime = new Date(result.genTime); } for (var i = 0; i < result.signers.length; i++) { var signer = result.signers[i]; $._processSignerModel(signer); } return result; }; $.filters = { isPkiBrazilPessoaFisica: function (cert) { if (typeof cert == 'undefined') { throw 'filter called without cert argument (hint: if you are using "pki.filters.isPkiBrazilPessoaFisica()", try "pki.filters.isPkiBrazilPessoaFisica")'; } return (cert.pkiBrazil && (cert.pkiBrazil.cpf || '') !== '' && (cert.pkiBrazil.cnpj || '') === ''); }, hasPkiBrazilCpf: function (cert) { if (typeof cert == 'undefined') { throw 'filter called without cert argument (hint: if you are using "pki.filters.hasPkiBrazilCpf()", try "pki.filters.hasPkiBrazilCpf")'; } return (cert.pkiBrazil && (cert.pkiBrazil.cpf || '') !== ''); }, hasPkiBrazilCnpj: function (cert) { if (typeof cert == 'undefined') { throw 'filter called without cert argument (hint: if you are using "pki.filters.hasPkiBrazilCnpj()", try "pki.filters.hasPkiBrazilCnpj")'; } return (cert.pkiBrazil && (cert.pkiBrazil.cnpj || '') !== ''); }, pkiBrazilCpfEquals: function (cpf) { if (typeof cpf !== 'string') { throw 'cpf must be a string (hint: if you are using "pki.filters.pkiBrazilCpfEquals", try "pki.filters.pkiBrazilCpfEquals(' + "'" + 'somecpf' + "'" + ')")'; } return function (cert) { return (cert.pkiBrazil && cert.pkiBrazil.cpf === cpf); }; }, pkiBrazilCnpjEquals: function (cnpj) { if (typeof cnpj !== 'string') { throw 'cnpj must be a string (hint: if you are using "pki.filters.pkiBrazilCnpjEquals", try "pki.filters.pkiBrazilCnpjEquals(' + "'" + 'somecnpj' + "'" +')")'; } return function (cert) { return (cert.pkiBrazil && cert.pkiBrazil.cnpj === cnpj); }; }, hasPkiItalyCodiceFiscale: function (cert) { if (typeof cert == 'undefined') { throw 'filter called without cert argument (hint: if you are using "pki.filters.hasPkiItalyCodiceFiscale()", try "pki.filters.hasPkiItalyCodiceFiscale")'; } return (cert.pkiItaly && (cert.pkiItaly.codiceFiscale || '') !== ''); }, pkiItalyCodiceFiscaleEquals: function (cf) { if (typeof cf !== 'string') { throw 'cf must be a string (hint: if you are using "pki.filters.pkiItalyCodiceFiscaleEquals", try "pki.filters.pkiItalyCodiceFiscaleEquals(' + "'" + 'someCodice' + "'" + ')")'; } return function (cert) { return (cert.pkiItaly && cert.pkiItaly.codiceFiscale === cf); }; }, isWithinValidity: function (cert) { if (typeof cert == 'undefined') { throw 'filter called without cert argument (hint: if you are using "pki.filters.isWithinValidity()", try "pki.filters.isWithinValidity")'; } var now = new Date(); return (cert.validityStart <= now && now <= cert.validityEnd); }, all: function () { var filters; if (arguments.length === 1 && typeof arguments[0] === 'object') { filters = arguments[0]; } else { filters = arguments; } return function (cert) { for (var i = 0; i < filters.length; i++) { var filter = filters[i]; if (!filter(cert)) { return false; } } return true; }; }, any: function () { var filters; if (arguments.length === 1 && typeof arguments[0] === 'object') { filters = arguments[0]; } else { filters = arguments; } return function (cert) { for (var i = 0; i < filters.length; i++) { var filter = filters[i]; if (filter(cert)) { return true; } } return false; }; } }; $.readCertificate = function (args) { if (typeof args === 'string') { args = { thumbprint: args }; } var context = this._createContext(args); $._requestHandler.sendCommand(context, 'readCertificate', { certificateThumbprint: args.thumbprint }); return context.promise; }; $.pollNative = function (args) { if (!args) { args = {}; } var context = this._createContext(args); var apiVersion = args.requiredApiVersion; if (!apiVersion) { apiVersion = $.apiVersions.latest; } if (!$._apiMap.nativeWin[apiVersion]) { throw 'Unknown JSlib API version: ' + apiVersion; } $._requestHandler.sendCommand(context, 'pollNative', { requiredNativeWinVersion: $._apiMap.nativeWin[apiVersion], requiredNativeLinuxVersion: $._apiMap.nativeLinux[apiVersion], requiredNativeMacVersion: $._apiMap.nativeMac[apiVersion] }); return context.promise; }; $.signHash = function (args) { var context = this._createContext(args); var request = { certificateThumbprint: args.thumbprint, hash: args.hash, digestAlgorithm: args.digestAlgorithm }; $._requestHandler.sendCommand(context, 'signHash', request); return context.promise; }; $.signData = function (args) { var context = this._createContext(args); var request = { certificateThumbprint: args.thumbprint, data: args.data, digestAlgorithm: args.digestAlgorithm }; $._requestHandler.sendCommand(context, 'signData', request); return context.promise; }; $.keySignHash = function (args) { var context = this._createContext(args); var request = { privateKeyId: args.privateKeyId, hash: args.hash, digestAlgorithm: args.digestAlgorithm, pkcs11Modules: $._getRequestOsP11Modules(args.pkcs11Modules), tokenSerialNumber: args.tokenSerialNumber }; $._handleP11ModulesArgs(args, request); $._requestHandler.sendCommand(context, 'keySignHash', request); return context.promise; }; $.keySignData = function (args) { var context = this._createContext(args); var request = { privateKeyId: args.privateKeyId, data: args.data, digestAlgorithm: args.digestAlgorithm, pkcs11Modules: $._getRequestOsP11Modules(args.pkcs11Modules), tokenSerialNumber: args.tokenSerialNumber }; $._handleP11ModulesArgs(args, request); $._requestHandler.sendCommand(context, 'keySignData', request); return context.promise; }; $.signWithRestPki = function (args) { var context = this._createContext(args); var request = { certificateThumbprint: args.thumbprint, token: args.token, restPkiUrl: this.restPkiUrl }; $._requestHandler.sendCommand(context, 'signWithRestPki', request); return context.promise; }; $.signHashBatch = function (args) { var context = this._createContext(args); var request = { certificateThumbprint: args.certificateThumbprint, digestAlgorithm: args.digestAlgorithm, usePreauthorizedSignatures: args.usePreauthorizedSignatures, batch: args.batch }; $._requestHandler.sendCommand(context, 'signHashBatch', request); return context.promise; }; $.signHashes = function (args) { var context = this._createContext(args); var request = { certificateThumbprint: args.certificateThumbprint, hashes: args.hashes }; $._requestHandler.sendCommand(context, 'signHashes', request); return context.promise; }; $.preauthorizeSignatures = function (args) { if (!args) { args = {}; } var context = this._createContext(args); var request = { certificateThumbprint: args.certificateThumbprint, signatureCount: args.signatureCount }; $._requestHandler.sendCommand(context, 'preauthorizeSignatures', request); return context.promise; }; $.showFolderBrowser = function (args) { if (!args) { args = {}; } else if (typeof args === 'string') { args = { message: args }; } var context = this._createContext(args); var request = { message: args.message }; $._requestHandler.sendCommand(context, 'showFolderBrowser', request); return context.promise; }; $.showFileBrowser = function (args) { if (!args) { args = {}; } var context = this._createContext(args); var request = { multiselect: args.multiselect, filters: args.filters, dialogTitle: args.dialogTitle }; $._requestHandler.sendCommand(context, 'showFileBrowser', request); return context.promise; }; $.downloadToFolder = function (args) { if (!args) { args = {}; } var url = args.url || ''; if (url.indexOf('://') < 0) { var a = document.createElement('a'); a.href = url; url = a.href; } var context = this._createContext(args); var request = { url: url, folderId: args.folderId, filename: args.filename }; $._requestHandler.sendCommand(context, 'downloadToFolder', request); return context.promise; }; $.openFolder = function (args) { if (!args) { args = {}; } else if (typeof args === 'string') { args = { folderId: args }; } var context = this._createContext(args); $._requestHandler.sendCommand(context, 'openFolder', args.folderId); return context.promise; }; $.openFile = function (args) { if (!args) { args = {}; } else if (typeof args === 'string') { args = { fileId: args }; } var context = this._createContext(args); $._requestHandler.sendCommand(context, 'openFile', args.fileId); return context.promise; }; $.redirectToInstallPage = function () { document.location.href = $._installUrl + (this.brand || '') + '?returnUrl=' + encodeURIComponent(document.URL) + '&jslib=' + $._jslibVersion; }; $.updateExtension = function (args) { if (!args) { args = {}; } var context = this._createContext(args); $._requestHandler.sendCommand(context, 'updateExtension', null); return context.promise; }; // -------------------- Web PKI Pro functions -------------------------- $._createCommonSignerRequest = function(args) { if (!args.output) { throw 'An output parameter must be passed to signer methods'; } return { fileId: args.fileId, content: args.content, certificateThumbprint: args.certificateThumbprint, output: { mode: args.output.mode, folderId: args.output.folderId, dialogTitle: args.output.dialogTitle, fileNameSuffix: args.output.fileNameSuffix }, trustArbitrators: args.trustArbitrators, clearPolicyTrustArbitrators: args.clearPolicyTrustArbitrators, certificateValidationLevel: args.certificateValidationLevel, timestampRequester: args.timestampRequester, policy: args.policy }; }; $.signPdf = function (args) { var context = this._createContext(args); var request = $._createCommonSignerRequest(args); request.visualRepresentation = args.visualRepresentation; request.pdfMarks = args.pdfMarks; request.bypassMarksIfSigned = args.bypassMarksIfSigned; request.reason = args.reason; request.location = args.location; request.signerName = args.signerName; request.customSignatureFieldName = args.customSignatureFieldName; if (typeof args.metadata === 'object') { request.metadata = {}; var metaKeys = Object.keys(args.metadata); for (var i=0; i<metaKeys.length; i++) { var curKey = metaKeys[i]; // ensure string values only if (typeof args.metadata[curKey] != 'string') { throw 'Only string values allowed on metadata dictionary. Found type ' + typeof args.metadata[curKey] + ': ' + curKey + ':' + args.metadata[curKey]; } request.metadata[curKey] = args.metadata[curKey]; } } if (request.visualRepresentation && request.visualRepresentation.image && request.visualRepresentation.image.resource && !request.visualRepresentation.image.resource.content && request.visualRepresentation.image.resource.url && !/^(https?:)?\/\//.exec(request.visualRepresentation.image.resource.url)) { $._downloadResource(request.visualRepresentation.image.resource.url, function (resource) { request.visualRepresentation.image.resource = resource; $._requestHandler.sendCommand(context, 'signPdf', request, $._processSignResult); }); } else { $._requestHandler.sendCommand(context, 'signPdf', request, $._processSignResult); } return context.promise; }; $.signCades = function (args) { var context = this._createContext(args); var request = $._createCommonSignerRequest(args); request.cmsToCosignFileId = args.cmsToCosignFileId; request.cmsToCosignContent = args.cmsToCosignContent; request.autoDetectCosign = args.autoDetectCosign; request.includeEncapsulatedContent = args.includeEncapsulatedContent === null || args.includeEncapsulatedContent === undefined ? true : args.includeEncapsulatedContent; request.signingDescription = args.signingDescription; $._requestHandler.sendCommand(context, 'signCades', request, $._processSignResult); return context.promise; }; $.signFullXml = function (args) { var context = this._createContext(args); var request = $._createCommonSignerRequest(args); request.signerType = 'fullXml'; $._signXmlCommon(args, request, context); return context.promise; }; $.signXmlElement = function (args) { var context = this._createContext(args); var request = $._createCommonSignerRequest(args); request.signerType = 'xmlElement'; request.toSignElementId = args.toSignElementId; request.toSignElementsIds = args.toSignElementsIds; request.toSignElementsXPath = args.toSignElementsXPath; request.idResolutionTable = args.idResolutionTable; $._signXmlCommon(args, request, context); return context.promise; }; $._signXmlCommon = function (args, request, context) { request.signatureElementId = args.signatureElementId; request.signingDescription = args.signingDescription; if (args.signatureElementLocation) { request.signatureElementLocation = { xpath: args.signatureElementLocation.xpath, insertionOption: args.signatureElementLocation.insertionOption }; } request.namespaces = args.namespaces; $._requestHandler.sendCommand(context, 'signXml', request, $._processSignResult); }; $._createCommonOpenRequest = function(args) { return { signatureFileId: args.signatureFileId, signatureContent: args.signatureContent, validate: args.validate, dateReference: args.dateReference, trustArbitrators: args.trustArbitrators, clearPolicyTrustArbitrators: args.clearPolicyTrustArbitrators, specificPolicy: args.specificPolicy }; }; $.openPades = function (args) { var context = this._createContext(args); var request = $._createCommonOpenRequest(args); $._requestHandler.sendCommand(context, 'openPades', request, $._processOpenResult); return context.promise; }; $.openCades = function (args) { var context = this._createContext(args); var request = $._createCommonOpenRequest(args); request.originalFileId = args.originalFileId; request.originalContent = args.originalContent; request.acceptablePolicies = args.acceptablePolicies; request.returnEncapsulatedContent = args.returnEncapsulatedContent; $._requestHandler.sendCommand(context, 'openCades', request, $._processOpenResult); return context.promise; }; $.openXmlSignature = function (args) { var context = this._createContext(args); var request = $._createCommonOpenRequest(args); request.idResolutionTable = args.idResolutionTable; request.acceptablePolicies = args.acceptablePolicies; $._requestHandler.sendCommand(context, 'openXmlSignature', request, $._processOpenResult); return context.promise; }; $.listTokens = function(args) { var context = this._createContext(args); var request = { pkcs11Modules: $._getRequestOsP11Modules(args.pkcs11Modules) }; $._requestHandler.sendCommand(context, 'listTokens', request); return context.promise; }; $.generateTokenRsaKeyPair = function(args) { var context = this._createContext(args); var request = { pkcs11Modules: $._getRequestOsP11Modules(args.pkcs11Modules), subjectName: args.subjectName, tokenSerialNumber: args.tokenSerialNumber, keyLabel: args.keyLabel, keySize: args.keySize, enableUsedPkcs11Module: args.enableUsedPkcs11Module }; $._handleP11ModulesArgs(args, request); $._requestHandler.sendCommand(context, 'generateTokenRsaKeyPair', request); return context.promise; }; $.generateSoftwareRsaKeyPair = function(args) { var context = this._createContext(args); var request = { subjectName: args.subjectName, keySize: args.keySize, nonExportableKey: args.nonExportableKey }; $._requestHandler.sendCommand(context, 'generateSoftwareRsaKeyPair', request); return context.promise; }; $.importTokenCertificate = function(args) { var context = this._createContext(args); var request = { privateKeyId: args.privateKeyId, pkcs11Modules: $._getRequestOsP11Modules(args.pkcs11Modules), tokenSerialNumber: args.tokenSerialNumber, certificateContent: args.certificateContent, caCertificates: args.caCertificates, certificateLabel: args.certificateLabel, enableUsedPkcs11Module: args.enableUsedPkcs11Module }; $._handleP11ModulesArgs(args, request); $._requestHandler.sendCommand(context, 'importTokenCertificate', request); return context.promise; }; $.importCertificate = function(args) { var context = this._createContext(args); var request = { privateKeyId: args.privateKeyId, certificateContent: args.certificateContent, caCertificates: args.caCertificates, passwordPolicies: args.passwordPolicies, passwordMinLength: args.passwordMinLength, savePkcs12: args.savePkcs12 }; $._requestHandler.sendCommand(context, 'importCertificate', request); return context.promise; }; $.sendAuthenticatedRequest = function(args) { var context = this._createContext(args); var request = { certificateThumbprint: args.certificateThumbprint, method: args.method, headers: args.headers, body: args.body, url: args.url }; $._requestHandler.sendCommand(context, 'sendAuthenticatedRequest', request); return context.promise; }; $.getGeolocation = function (args) { var context = this._createContext(args); var request = { certificateThumbprint: args.certificateThumbprint }; $._requestHandler.sen