UNPKG

@phemium-costaisa/fingerprint-auth

Version:

Automatic plugin to work with FaceID and TouchID authentication

1,211 lines 60.8 kB
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@ionic-native/fingerprint-aio/ngx'), require('@ionic-native/android-fingerprint-auth/ngx'), require('@ionic-native/touch-id/ngx'), require('@ionic-native/keychain/ngx'), require('@ionic/angular'), require('@ngx-translate/core'), require('rxjs'), require('rxjs/operators'), require('@angular/router'), require('@ionic/storage-angular'), require('@angular/common'), require('@angular/forms')) :
    typeof define === 'function' && define.amd ? define('@phemium-costaisa/fingerprint-auth', ['exports', '@angular/core', '@ionic-native/fingerprint-aio/ngx', '@ionic-native/android-fingerprint-auth/ngx', '@ionic-native/touch-id/ngx', '@ionic-native/keychain/ngx', '@ionic/angular', '@ngx-translate/core', 'rxjs', 'rxjs/operators', '@angular/router', '@ionic/storage-angular', '@angular/common', '@angular/forms'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global["phemium-costaisa"] = global["phemium-costaisa"] || {}, global["phemium-costaisa"]["fingerprint-auth"] = {}), global.ng.core, global.ngx, global.ngx$1, global.ngx$2, global.ngx$3, global.angular, global.core$1, global.rxjs, global.rxjs.operators, global.ng.router, global.storageAngular, global.ng.common, global.ng.forms));
})(this, (function (exports, core, ngx, ngx$1, ngx$2, ngx$3, angular, core$1, rxjs, operators, router, storageAngular, common, forms) { 'use strict';

    /******************************************************************************
    Copyright (c) Microsoft Corporation.

    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted.

    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    PERFORMANCE OF THIS SOFTWARE.
    ***************************************************************************** */
    /* global Reflect, Promise */
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b)
                if (Object.prototype.hasOwnProperty.call(b, p))
                    d[p] = b[p]; };
        return extendStatics(d, b);
    };
    function __extends(d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    }
    var __assign = function () {
        __assign = Object.assign || function __assign(t) {
            for (var s, i = 1, n = arguments.length; i < n; i++) {
                s = arguments[i];
                for (var p in s)
                    if (Object.prototype.hasOwnProperty.call(s, p))
                        t[p] = s[p];
            }
            return t;
        };
        return __assign.apply(this, arguments);
    };
    function __rest(s, e) {
        var t = {};
        for (var p in s)
            if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
                t[p] = s[p];
        if (s != null && typeof Object.getOwnPropertySymbols === "function")
            for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
                if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                    t[p[i]] = s[p[i]];
            }
        return t;
    }
    function __decorate(decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
            r = Reflect.decorate(decorators, target, key, desc);
        else
            for (var i = decorators.length - 1; i >= 0; i--)
                if (d = decorators[i])
                    r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    }
    function __param(paramIndex, decorator) {
        return function (target, key) { decorator(target, key, paramIndex); };
    }
    function __metadata(metadataKey, metadataValue) {
        if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
            return Reflect.metadata(metadataKey, metadataValue);
    }
    function __awaiter(thisArg, _arguments, P, generator) {
        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try {
                step(generator.next(value));
            }
            catch (e) {
                reject(e);
            } }
            function rejected(value) { try {
                step(generator["throw"](value));
            }
            catch (e) {
                reject(e);
            } }
            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    }
    function __generator(thisArg, body) {
        var _ = { label: 0, sent: function () { if (t[0] & 1)
                throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
        return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
        function verb(n) { return function (v) { return step([n, v]); }; }
        function step(op) {
            if (f)
                throw new TypeError("Generator is already executing.");
            while (_)
                try {
                    if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
                        return t;
                    if (y = 0, t)
                        op = [op[0] & 2, t.value];
                    switch (op[0]) {
                        case 0:
                        case 1:
                            t = op;
                            break;
                        case 4:
                            _.label++;
                            return { value: op[1], done: false };
                        case 5:
                            _.label++;
                            y = op[1];
                            op = [0];
                            continue;
                        case 7:
                            op = _.ops.pop();
                            _.trys.pop();
                            continue;
                        default:
                            if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                                _ = 0;
                                continue;
                            }
                            if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
                                _.label = op[1];
                                break;
                            }
                            if (op[0] === 6 && _.label < t[1]) {
                                _.label = t[1];
                                t = op;
                                break;
                            }
                            if (t && _.label < t[2]) {
                                _.label = t[2];
                                _.ops.push(op);
                                break;
                            }
                            if (t[2])
                                _.ops.pop();
                            _.trys.pop();
                            continue;
                    }
                    op = body.call(thisArg, _);
                }
                catch (e) {
                    op = [6, e];
                    y = 0;
                }
                finally {
                    f = t = 0;
                }
            if (op[0] & 5)
                throw op[1];
            return { value: op[0] ? op[1] : void 0, done: true };
        }
    }
    var __createBinding = Object.create ? (function (o, m, k, k2) {
        if (k2 === undefined)
            k2 = k;
        var desc = Object.getOwnPropertyDescriptor(m, k);
        if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
            desc = { enumerable: true, get: function () { return m[k]; } };
        }
        Object.defineProperty(o, k2, desc);
    }) : (function (o, m, k, k2) {
        if (k2 === undefined)
            k2 = k;
        o[k2] = m[k];
    });
    function __exportStar(m, o) {
        for (var p in m)
            if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
                __createBinding(o, m, p);
    }
    function __values(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m)
            return m.call(o);
        if (o && typeof o.length === "number")
            return {
                next: function () {
                    if (o && i >= o.length)
                        o = void 0;
                    return { value: o && o[i++], done: !o };
                }
            };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    }
    function __read(o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m)
            return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
                ar.push(r.value);
        }
        catch (error) {
            e = { error: error };
        }
        finally {
            try {
                if (r && !r.done && (m = i["return"]))
                    m.call(i);
            }
            finally {
                if (e)
                    throw e.error;
            }
        }
        return ar;
    }
    /** @deprecated */
    function __spread() {
        for (var ar = [], i = 0; i < arguments.length; i++)
            ar = ar.concat(__read(arguments[i]));
        return ar;
    }
    /** @deprecated */
    function __spreadArrays() {
        for (var s = 0, i = 0, il = arguments.length; i < il; i++)
            s += arguments[i].length;
        for (var r = Array(s), k = 0, i = 0; i < il; i++)
            for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
                r[k] = a[j];
        return r;
    }
    function __spreadArray(to, from, pack) {
        if (pack || arguments.length === 2)
            for (var i = 0, l = from.length, ar; i < l; i++) {
                if (ar || !(i in from)) {
                    if (!ar)
                        ar = Array.prototype.slice.call(from, 0, i);
                    ar[i] = from[i];
                }
            }
        return to.concat(ar || Array.prototype.slice.call(from));
    }
    function __await(v) {
        return this instanceof __await ? (this.v = v, this) : new __await(v);
    }
    function __asyncGenerator(thisArg, _arguments, generator) {
        if (!Symbol.asyncIterator)
            throw new TypeError("Symbol.asyncIterator is not defined.");
        var g = generator.apply(thisArg, _arguments || []), i, q = [];
        return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
        function verb(n) { if (g[n])
            i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
        function resume(n, v) { try {
            step(g[n](v));
        }
        catch (e) {
            settle(q[0][3], e);
        } }
        function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
        function fulfill(value) { resume("next", value); }
        function reject(value) { resume("throw", value); }
        function settle(f, v) { if (f(v), q.shift(), q.length)
            resume(q[0][0], q[0][1]); }
    }
    function __asyncDelegator(o) {
        var i, p;
        return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
        function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
    }
    function __asyncValues(o) {
        if (!Symbol.asyncIterator)
            throw new TypeError("Symbol.asyncIterator is not defined.");
        var m = o[Symbol.asyncIterator], i;
        return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
        function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
        function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
    }
    function __makeTemplateObject(cooked, raw) {
        if (Object.defineProperty) {
            Object.defineProperty(cooked, "raw", { value: raw });
        }
        else {
            cooked.raw = raw;
        }
        return cooked;
    }
    ;
    var __setModuleDefault = Object.create ? (function (o, v) {
        Object.defineProperty(o, "default", { enumerable: true, value: v });
    }) : function (o, v) {
        o["default"] = v;
    };
    function __importStar(mod) {
        if (mod && mod.__esModule)
            return mod;
        var result = {};
        if (mod != null)
            for (var k in mod)
                if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
                    __createBinding(result, mod, k);
        __setModuleDefault(result, mod);
        return result;
    }
    function __importDefault(mod) {
        return (mod && mod.__esModule) ? mod : { default: mod };
    }
    function __classPrivateFieldGet(receiver, state, kind, f) {
        if (kind === "a" && !f)
            throw new TypeError("Private accessor was defined without a getter");
        if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
            throw new TypeError("Cannot read private member from an object whose class did not declare it");
        return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
    }
    function __classPrivateFieldSet(receiver, state, value, kind, f) {
        if (kind === "m")
            throw new TypeError("Private method is not writable");
        if (kind === "a" && !f)
            throw new TypeError("Private accessor was defined without a setter");
        if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
            throw new TypeError("Cannot write private member to an object whose class did not declare it");
        return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
    }
    function __classPrivateFieldIn(state, receiver) {
        if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function"))
            throw new TypeError("Cannot use 'in' operator on non-object");
        return typeof state === "function" ? receiver === state : state.has(receiver);
    }

    var StorageService = /** @class */ (function () {
        function StorageService() {
            this._storage = null;
            this.init();
        }
        StorageService.prototype.init = function () {
            return __awaiter(this, void 0, void 0, function () {
                var storageConfig, myStorage, _b;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            storageConfig = {
                                name: '_biometricstorage',
                                storeName: '_biometrickv',
                                dbKey: '_biometrickey'
                            };
                            myStorage = new storageAngular.Storage(storageConfig);
                            _b = this;
                            return [4 /*yield*/, myStorage.create()];
                        case 1:
                            _b._storage = _c.sent();
                            return [2 /*return*/];
                    }
                });
            });
        };
        StorageService.prototype.set = function (key, value) {
            var _a;
            return (_a = this._storage) === null || _a === void 0 ? void 0 : _a.set(key, value);
        };
        StorageService.prototype.get = function (key) {
            var _a;
            return (_a = this._storage) === null || _a === void 0 ? void 0 : _a.get(key);
        };
        StorageService.prototype.remove = function (key) {
            return this._storage.remove(key);
        };
        StorageService.prototype.clear = function () {
            return this._storage.clear();
        };
        StorageService.prototype.keys = function () {
            return this._storage.keys();
        };
        return StorageService;
    }());
    StorageService.decorators = [
        { type: core.Injectable }
    ];
    StorageService.ctorParameters = function () { return []; };

    /** InjectionToken for Global Configuration */
    var Config = new core.InjectionToken('PLUGIN_CONFIGURATION');

    var Biometric;
    (function (Biometric) {
        Biometric["Face"] = "face";
        Biometric["Fingerprint"] = "finger";
        Biometric["Common"] = "biometric";
    })(Biometric || (Biometric = {}));
    var FingerprintService = /** @class */ (function () {
        function FingerprintService(platform, faio, androidFingerprintAuth, touchId, keychain, router, storage, translateService, config) {
            this.platform = platform;
            this.faio = faio;
            this.androidFingerprintAuth = androidFingerprintAuth;
            this.touchId = touchId;
            this.keychain = keychain;
            this.router = router;
            this.storage = storage;
            this.translateService = translateService;
            this.config = config;
        }
        /**
         * Use this method in Login page to check if user
         * should be redirected to the Biometric Activator
         */
        FingerprintService.prototype.checkIfNeedsBiometric = function (user) {
            return __awaiter(this, void 0, void 0, function () {
                var biometricFaceActive, biometricTouchActive, biometricCapabilities, isBiometricCapable;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0:
                            if (!this.isPlatformMobile()) {
                                this.config.debug &&
                                    console.log('[BiometricService]', 'isPlatformMobile():', this.isPlatformMobile());
                                return [2 /*return*/, false];
                            }
                            return [4 /*yield*/, this.isBiometricActive(user, 'face')];
                        case 1:
                            biometricFaceActive = _b.sent();
                            this.config.debug &&
                                console.log('[BiometricService]', 'biometricFaceActive:', biometricFaceActive);
                            return [4 /*yield*/, this.isBiometricActive(user, 'touch')];
                        case 2:
                            biometricTouchActive = _b.sent();
                            this.config.debug &&
                                console.log('[BiometricService]', 'biometricTouchActive:', biometricTouchActive);
                            return [4 /*yield*/, this.retrieveDeviceBiometrics()];
                        case 3:
                            biometricCapabilities = _b.sent();
                            this.config.debug &&
                                console.log('[BiometricService]', 'biometricCapabilities:', biometricCapabilities);
                            isBiometricCapable = biometricCapabilities.face || biometricCapabilities.touch;
                            // Redirect to Biometric Activator if conditions are met
                            return [2 /*return*/, (biometricFaceActive === null &&
                                    biometricTouchActive === null &&
                                    isBiometricCapable)];
                    }
                });
            });
        };
        /**
         * Use in Login page to open Biometric prompt
         * @param user string
         */
        FingerprintService.prototype.showBiometricPrompt = function (user) {
            return __awaiter(this, void 0, void 0, function () {
                var face, touch, password, password;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0: return [4 /*yield*/, this.showFingerprintId(user, 'face').toPromise()];
                        case 1:
                            face = _b.sent();
                            return [4 /*yield*/, this.showFingerprintId(user, 'touch').toPromise()];
                        case 2:
                            touch = _b.sent();
                            if (!face) return [3 /*break*/, 4];
                            return [4 /*yield*/, this.launchFaceID(user)];
                        case 3:
                            password = _b.sent();
                            if (password) {
                                return [2 /*return*/, { user: user, password: password }];
                            }
                            else {
                                throw 'Something went wrong in launchFaceID';
                            }
                            return [3 /*break*/, 7];
                        case 4:
                            if (!touch) return [3 /*break*/, 6];
                            return [4 /*yield*/, this.launchTouchID(user)];
                        case 5:
                            password = _b.sent();
                            if (password) {
                                return [2 /*return*/, { user: user, password: password }];
                            }
                            else {
                                throw 'Something went wrong in launchTouchID';
                            }
                            return [3 /*break*/, 7];
                        case 6: throw 'Looks like we have an error in our code.';
                        case 7: return [2 /*return*/];
                    }
                });
            });
        };
        FingerprintService.prototype._iosShowTouchPrompt = function () {
            return __awaiter(this, void 0, void 0, function () {
                var err_1;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0:
                            _b.trys.push([0, 2, , 3]);
                            return [4 /*yield*/, this.touchId.verifyFingerprintWithCustomPasswordFallback('Scan your fingerprint please')];
                        case 1: return [2 /*return*/, _b.sent()];
                        case 2:
                            err_1 = _b.sent();
                            // -3 code means the user used the Use Password fallback, which is ok for us
                            if ((err_1 === null || err_1 === void 0 ? void 0 : err_1.code) !== -3) {
                                throw err_1;
                            }
                            return [2 /*return*/, true];
                        case 3: return [2 /*return*/];
                    }
                });
            });
        };
        FingerprintService.prototype._sanitizeUser = function (user) {
            return ("" + user).toLowerCase();
        };
        FingerprintService.prototype._getStorageKey = function (user, biometricType) {
            user = this._sanitizeUser(user);
            return "biometricLoginActive_" + biometricType + "_" + user;
        };
        FingerprintService.prototype._getStorageToken = function (user, biometricType) {
            user = this._sanitizeUser(user);
            return "token_" + biometricType + "_" + user;
        };
        FingerprintService.prototype.getLang = function () {
            var _a;
            return ((_a = this.translateService) === null || _a === void 0 ? void 0 : _a.currentLang) || 'es';
        };
        FingerprintService.prototype.isBiometricActive = function (user, biometricType) {
            return __awaiter(this, void 0, void 0, function () {
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0: return [4 /*yield*/, this.storage.get(this._getStorageKey(user, biometricType))];
                        case 1: return [2 /*return*/, _b.sent()];
                    }
                });
            });
        };
        FingerprintService.prototype.isPlatformMobile = function () {
            return (this.platform.is('ios') ||
                this.platform.is('ipad') ||
                this.platform.is('iphone') ||
                this.platform.is('android'));
        };
        FingerprintService.prototype.clearBiometricData = function (user, biometricType) {
            return __awaiter(this, void 0, void 0, function () {
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0: return [4 /*yield*/, this.storage.remove(this._getStorageKey(user, biometricType))];
                        case 1:
                            _b.sent();
                            return [4 /*yield*/, this.storage.remove(this._getStorageToken(user, biometricType))];
                        case 2:
                            _b.sent();
                            if (!this._isIOS()) return [3 /*break*/, 4];
                            return [4 /*yield*/, this.keychain.remove(this._getStorageToken(user, biometricType))];
                        case 3:
                            _b.sent();
                            _b.label = 4;
                        case 4: return [2 /*return*/];
                    }
                });
            });
        };
        FingerprintService.prototype.disableBiometricData = function (user, biometricType) {
            return __awaiter(this, void 0, void 0, function () {
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0: return [4 /*yield*/, this.storage.set(this._getStorageKey(user, biometricType), false)];
                        case 1:
                            _b.sent();
                            return [4 /*yield*/, this.storage.remove(this._getStorageToken(user, biometricType))];
                        case 2:
                            _b.sent();
                            if (!this._isIOS()) return [3 /*break*/, 4];
                            return [4 /*yield*/, this.keychain.remove(this._getStorageToken(user, biometricType))];
                        case 3:
                            _b.sent();
                            _b.label = 4;
                        case 4: return [2 /*return*/];
                    }
                });
            });
        };
        FingerprintService.prototype.showFingerprintId = function (user, biometricType) {
            var _this = this;
            this.config.debug &&
                console.log('[BiometricService]', 'showFingerPrintId with type:', biometricType);
            this.config.debug &&
                console.log('[BiometricService]', 'Is IOS:', this._isIOS());
            // Retrieve the getter for iOS or Android
            var tokenPromise = this._isIOS()
                ? this.keychain.get(this._getStorageToken(user, biometricType))
                : this.storage.get(this._getStorageToken(user, biometricType));
            this.config.debug &&
                console.log('[BiometricService]', 'Token Promise:', tokenPromise);
            // User user to retrieve status of biometric and check if it has token
            return rxjs.forkJoin([
                rxjs.from(this.storage.get(this._getStorageKey(user, biometricType))),
                rxjs.from(tokenPromise),
            ]).pipe(operators.tap(function (_b) {
                var _c = __read(_b, 2), active = _c[0], token = _c[1];
                return _this.config.debug &&
                    console.log('[BiometricService]', 'Biometric result |', 'Active:', active, 'Token:', token);
            }), operators.map(function (_b) {
                var _c = __read(_b, 2), active = _c[0], token = _c[1];
                return !!active && !!token;
            }));
        };
        /**
         * Use in Login page to show the Biometric Activator page
         * @param user User
         * @param password Password
         * @param callbackUrl URL to return after success or fail
         */
        FingerprintService.prototype.showBiometricActivator = function (user, password, callbackUrl) {
            this.router.navigate(['biometric-activator'], {
                queryParams: { user: user, password: password, callbackUrl: callbackUrl },
            });
        };
        /**
         * Checks and returns which biometrics methods are available
         * for the current device
         * @returns Promise<Biometric[]>
         */
        FingerprintService.prototype.retrieveDeviceBiometrics = function () {
            return __awaiter(this, void 0, void 0, function () {
                var iosResult, androidResult, err_2, err_3;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0: return [4 /*yield*/, this.platform.ready()];
                        case 1:
                            _b.sent();
                            iosResult = '';
                            androidResult = null;
                            if (!this._isIOS()) return [3 /*break*/, 6];
                            _b.label = 2;
                        case 2:
                            _b.trys.push([2, 4, , 5]);
                            return [4 /*yield*/, this.touchId.isAvailable()];
                        case 3:
                            iosResult = _b.sent();
                            return [3 /*break*/, 5];
                        case 4:
                            err_2 = _b.sent();
                            return [3 /*break*/, 5];
                        case 5: return [3 /*break*/, 9];
                        case 6:
                            _b.trys.push([6, 8, , 9]);
                            return [4 /*yield*/, this.androidFingerprintAuth.isAvailable()];
                        case 7:
                            androidResult = _b.sent();
                            return [3 /*break*/, 9];
                        case 8:
                            err_3 = _b.sent();
                            return [3 /*break*/, 9];
                        case 9: return [2 /*return*/, {
                                face: iosResult === 'face',
                                touch: iosResult === 'touch' || (androidResult === null || androidResult === void 0 ? void 0 : androidResult.isAvailable) || false,
                            }];
                    }
                });
            });
        };
        FingerprintService.prototype._isIOS = function () {
            return (this.platform.is('ios') ||
                this.platform.is('ipad') ||
                this.platform.is('iphone'));
        };
        /**
         * Stores the credentials used for biometrics
         * @param user Client user
         * @param password Client password
         */
        FingerprintService.prototype._storePassword = function (user, password, biometricType) {
            return __awaiter(this, void 0, void 0, function () {
                var biometric, fingerprint, fingerprintResult;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0:
                            if (!this._isIOS()) return [3 /*break*/, 7];
                            return [4 /*yield*/, this.touchId.isAvailable()];
                        case 1:
                            biometric = _b.sent();
                            // Set Biometric login in storage
                            return [4 /*yield*/, this.storage.set(this._getStorageKey(user, biometricType), true)];
                        case 2:
                            // Set Biometric login in storage
                            _b.sent();
                            if (!(biometric == 'touch' || biometric == 'face')) return [3 /*break*/, 6];
                            if (!(biometric == 'touch')) return [3 /*break*/, 4];
                            return [4 /*yield*/, this._iosShowTouchPrompt()];
                        case 3:
                            _b.sent();
                            _b.label = 4;
                        case 4: 
                        // Although we define the prefix "token_", it doesn't actually contain a token,
                        // it will contain the password in the encrypted iOS storage
                        return [4 /*yield*/, this.keychain.set(this._getStorageToken(user, biometricType), password, false)];
                        case 5:
                            // Although we define the prefix "token_", it doesn't actually contain a token,
                            // it will contain the password in the encrypted iOS storage
                            _b.sent();
                            _b.label = 6;
                        case 6: return [3 /*break*/, 10];
                        case 7:
                            if (!this.platform.is('android')) return [3 /*break*/, 10];
                            return [4 /*yield*/, this.androidFingerprintAuth.isAvailable()];
                        case 8:
                            fingerprint = _b.sent();
                            if (!fingerprint.isAvailable) return [3 /*break*/, 10];
                            return [4 /*yield*/, this.androidFingerprintAuth.encrypt({
                                    clientId: user,
                                    username: user,
                                    password: password,
                                    locale: this.getLang(),
                                    disableBackup: true,
                                })];
                        case 9:
                            fingerprintResult = _b.sent();
                            if (fingerprintResult.withFingerprint) {
                                // User used fingerprint to decrypt password
                                this.storage.set(this._getStorageKey(user, biometricType), true);
                                this.storage.set(this._getStorageToken(user, biometricType), fingerprintResult.token);
                                this.config.debug &&
                                    console.log("Token (" + user + "): " + fingerprintResult.token);
                            }
                            else if (fingerprintResult.withBackup) {
                                // DEPRECATED: Disabled "Use backup" option from encrypt prompt as it is useless
                                // console.log('Successfully authenticated with backup password!');
                            }
                            else {
                                this.config.debug && console.log("Didn't authenticate!");
                            }
                            _b.label = 10;
                        case 10: return [2 /*return*/];
                    }
                });
            });
        };
        /**
         * Shows the FaceID dialog to the user
         * @param user Client user
         * @returns Promise<void>
         */
        FingerprintService.prototype.activateFaceID = function (user, password) {
            return __awaiter(this, void 0, void 0, function () {
                var biometricConfig, err_4;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0:
                            biometricConfig = {
                                cancelButtonTitle: 'Cancelar',
                                description: 'Activar FaceID',
                                disableBackup: true,
                                title: 'Activate',
                                fallbackButtonTitle: 'Back Button',
                                subtitle: 'Act',
                            };
                            _b.label = 1;
                        case 1:
                            _b.trys.push([1, 3, , 4]);
                            // Show FaceID dialog to user
                            return [4 /*yield*/, this.faio.show(biometricConfig)];
                        case 2:
                            // Show FaceID dialog to user
                            _b.sent();
                            return [3 /*break*/, 4];
                        case 3:
                            err_4 = _b.sent();
                            console.log('Match not found');
                            console.log(err_4);
                            return [3 /*break*/, 4];
                        case 4: 
                        // Save encrypted password
                        return [4 /*yield*/, this._storePassword(user, password, 'face')];
                        case 5:
                            // Save encrypted password
                            _b.sent();
                            return [2 /*return*/];
                    }
                });
            });
        };
        /**
         * Shows the TouchID dialog to the user
         * @param user Client user
         * @param password Client password
         */
        FingerprintService.prototype.activateTouchID = function (user, password) {
            return this._storePassword(user, password, 'touch');
        };
        /**
         * Executes an attempt to check for the client fingerprint
         * Used mainly in Login
         * @returns Promise<void>
         */
        FingerprintService.prototype.launchTouchID = function (user) {
            return __awaiter(this, void 0, void 0, function () {
                var password, fingerprintAvailable, token, fingerprintResult;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0:
                            if (!this._isIOS()) return [3 /*break*/, 4];
                            return [4 /*yield*/, this.touchId.isAvailable()];
                        case 1:
                            _b.sent(); // Will reject if not available
                            return [4 /*yield*/, this._iosShowTouchPrompt()];
                        case 2:
                            _b.sent(); // Will reject if fingerprint was failed
                            return [4 /*yield*/, this.keychain.get(this._getStorageToken(user, 'touch'))];
                        case 3:
                            password = (_b.sent());
                            if (password) {
                                return [2 /*return*/, password];
                            }
                            else {
                                console.log('Password not found in keychain');
                            }
                            return [3 /*break*/, 9];
                        case 4: return [4 /*yield*/, this.androidFingerprintAuth.isAvailable()];
                        case 5:
                            fingerprintAvailable = (_b.sent()).isAvailable;
                            if (!fingerprintAvailable) return [3 /*break*/, 9];
                            return [4 /*yield*/, this.storage.get(this._getStorageToken(user, 'touch'))];
                        case 6:
                            token = (_b.sent());
                            if (!token) return [3 /*break*/, 8];
                            return [4 /*yield*/, this.androidFingerprintAuth.decrypt({
                                    clientId: user,
                                    username: user,
                                    token: token,
                                    locale: this.getLang(),
                                })];
                        case 7:
                            fingerprintResult = _b.sent();
                            if (fingerprintResult.password) {
                                return [2 /*return*/, fingerprintResult.password];
                            }
                            else {
                                console.log('Password not found in decrypted fingerprint');
                            }
                            return [3 /*break*/, 9];
                        case 8:
                            console.log('Token not found in storage');
                            _b.label = 9;
                        case 9: return [2 /*return*/];
                    }
                });
            });
        };
        /**
         * Executes an attempt to check for the client face
         * Used mainly in Login
         * @returns Promise<void>
         */
        FingerprintService.prototype.launchFaceID = function (user) {
            return __awaiter(this, void 0, void 0, function () {
                var faceAvailable, err_5, password;
                return __generator(this, function (_b) {
                    switch (_b.label) {
                        case 0: return [4 /*yield*/, this.faio.isAvailable()];
                        case 1:
                            faceAvailable = _b.sent();
                            if (!faceAvailable) return [3 /*break*/, 7];
                            _b.label = 2;
                        case 2:
                            _b.trys.push([2, 4, , 5]);
                            return [4 /*yield*/, this.faio.show({
                                    cancelButtonTitle: 'Cancel',
                                    description: 'Acceder con FaceId',
                                    disableBackup: true,
                                    title: 'Scan',
                                    fallbackButtonTitle: 'FB back Button',
                                    subtitle: 'Subtitle',
                                })];
                        case 3:
                            _b.sent();
                            return [3 /*break*/, 5];
                        case 4:
                            err_5 = _b.sent();
                            console.log('No match found');
                            console.log(err_5);
                            return [2 /*return*/, null];
                        case 5: return [4 /*yield*/, this.keychain.get(this._getStorageToken(user, 'face'))];
                        case 6:
                            password = (_b.sent());
                            if (password) {
                                return [2 /*return*/, password];
                            }
                            else {
                                console.log('Password not found in keychain');
                            }
                            return [3 /*break*/, 8];
                        case 7:
                            console.log('FaceID is not available');
                            _b.label = 8;
                        case 8: return [2 /*return*/];
                    }
                });
            });
        };
        return FingerprintService;
    }());
    FingerprintService.decorators = [
        { type: core.Injectable }
    ];
    FingerprintService.ctorParameters = function () { return [
        { type: angular.Platform },
        { type: ngx.FingerprintAIO },
        { type: ngx$1.AndroidFingerprintAuth },
        { type: ngx$2.TouchID },
        { type: ngx$3.Keychain },
        { type: router.Router },
        { type: StorageService },
        { type: core$1.TranslateService, decorators: [{ type: core.Optional }] },
        { type: undefined, decorators: [{ type: core.Inject, args: [Config,] }] }
    ]; };

    var FingerprintMockService = /** @class */ (function () {
        function FingerprintMockService() {
        }
        /**
       * Use this method in Login page to check if user
       * should be redirected to the Biometric Activator
       */
        FingerprintMockService.prototype.checkIfNeedsBiometric = function (user) {
            return __awaiter(this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    return [2 /*return*/, Promise.resolve(false)];
                });
            });
        };
        /**
       * Use in Login page to show the Biometric Activator page
       * @param user User
       * @param password Password
       * @param callbackUrl URL to return after success or fail
       */
        FingerprintMockService.prototype.showBiometricActivator = function (user, password, callbackUrl) { };
        /**
         * Use in Login page to open Biometric prompt
         * @param user string
         */
        FingerprintMockService.prototype.showBiometricPrompt = function (user) {
            return __awaiter(this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    return [2 /*return*/, Promise.resolve({ user: user, password: null })];
                });
            });
        };
        /**
        * Checks and returns which biometrics methods are available
        * for the current device
        * @returns Promise<Biometric[]>
        */
        FingerprintMockService.prototype.retrieveDeviceBiometrics = function () {
            return __awaiter(this, void 0, void 0, function () {
                return __generator(this, function (_a) {
                    return [2 /*return*/, {
                            face: false,
                            touch: false
                        }];
                });
            });
        };
        /**
       * Shows the FaceID dialog to the user
       * @param user Client user
       * @returns Promise<void>
       */
        FingerprintMockService.prototype.activateFaceID = function (user, password) {
            return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
                return [2 /*return*/];
            }); });
        };
        /**
         * Shows the TouchID dialog to the user
         * @param user Client user
         * @param password Client password
         */
        FingerprintMockService.prototype.activateTouchID = function (user, password) { };
        FingerprintMockService.prototype.isBiometricActive = function (user, biometricType) {
            return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
                return [2 /*return*/];
            }); });
        };
        FingerprintMockService.prototype.clearBiometricData = function (user, biometricType) {
            return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
                return [2 /*return*/];
            }); });
        };
        FingerprintMockService.prototype.disableBiometricData = function (user, biometricType) {
            return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
                return [2 /*return*/];
            }); });
        };
        FingerprintMockService.prototype.showFingerprintId = function (user, biometricType) {
            return rxjs.of(false);
        };
        return FingerprintMockService;
    }());
    FingerprintMockService.decorators = [
        { type: core.Injectable }
    ];

    var BiometricLoginActivePipe = /** @class */ (function () {
        function BiometricLoginActivePipe(fingerprintService, platform, config) {
            this.fingerprintService = fingerprintService;
            this.platform = platform;
            this.config = config;
        }
        BiometricLoginActivePipe.prototype.transform = function (user) {
            var _this = this;
            this.config.debug && console.log('[BiometricLoginActive]', user);
            return rxjs.from(this.platform.ready()).pipe(operators.tap(function () { return _this.config.debug && console.log('[BiometricLoginActive]', 'Platform is ready'); }), operators.switchMap(function () {
                return rxjs.forkJoin([
                    _this.fingerprintService.showFingerprintId(user, 'face'),
                    _this.fingerprintService.showFingerprintId(user, 'touch')
                ]);
            }), operators.tap(function (_a) {
                var _b = __read(_a, 2), face = _b[0], touch = _b[1];
                return _this.config.debug && console.log('[BiometricLoginActive]', 'Face:', face, 'Touch:', touch);
            }), operators.map(function (_a) {
                var _b = __read(_a, 2), face = _b[0], touch = _b[1];
                return face || touch;
            }));
        };
        return BiometricLoginActivePipe;
    }());
    BiometricLoginActivePipe.decorators = [
        { type: core.Pipe, args: [{
                    name: 'biometricLoginActive'
                },] }
    ];
    BiometricLoginActivePipe.ctorParameters = function () { return [
        { type: FingerprintService },
        { type: angular.Platform },
        { type: undefined, decorators: [{ type: core.Inject, args: [Config,] }] }
    ]; };

    var defaultConfig = {
        debug: false,
        enabled: true
    };
    function initStorage(storageService) {
        return function () { return storageService.init(); };
    }
    var storageProvider = {
        provide: core.APP_INITIALIZER,
        useFactory: initStorage,
        deps: [StorageService],
        multi: true
    };
    var FingerprintAuthModule = /** @class */ (function () {
        function FingerprintAuthModule() {
        }
        FingerprintAuthModule.forRoot = function (options) {
            if (options === void 0) { options = {}; }
            options = Object.assign(defaultConfig, options);
            if (options.enabled) {
                return {
                    ngModule: FingerprintAuthModule,
                    providers: [
                        FingerprintService,
                        ngx$2.TouchID,
                        ngx$3.Keychain,
                        ngx.FingerprintAIO,
                        ngx$1.AndroidFingerprintAuth,
                        StorageService,
                        storageProvider,
                        { provide: Config, useValue: options }
                    ]
                };
            }
            else {
                // Mock service
                return {
                    ngModule: FingerprintAuthModule,
                    providers: [
                        {
                            provide: FingerprintService,
                            useClass: FingerprintMockService
                        },
                        ngx$2.TouchID,
                        ngx$3.Keychain,
                        ngx.FingerprintAIO,
                        ngx$1.AndroidFingerprintAuth,
                        StorageService,
                        storageProvider,
                        { provide: Config, useValue: options }
                    ]
                };
            }
        };
        FingerprintAuthModule.forChild = function () {
            return {
                ngModule: FingerprintAuthModule
            };
        };
        return FingerprintAuthModule;
    }());
    FingerprintAuthModule.decorators = [
        { type: core.NgModule, args: [{
                    declarations: [
                        BiometricLoginActivePipe
                    ],
                    exports: [
                        BiometricLoginActivePipe
                    ]
                },] }
    ];

    var BiometricActivator = /** @class */ (function () {
        function BiometricActivator(navCntrl, route, fingerprintService) {
            this.navCntrl = navCntrl;
            this.route = route;
            this.fingerprintService = fingerprintService;
            this.biometrics$ = rxjs.from(this.fingerprintService.retrieveDeviceBiometrics());
        }
        BiometricActivator.prototype.close = function () {
            var callbackUrl = this.route.snapshot.queryParamMap.get('callbackUrl');
            this.navCntrl.navigateForward(callbackUrl);
        };
        BiometricActivator.prototype.activateFaceID = function () {
            var _this = this;
            var callbackUrl = this.route.snapshot.queryParamMap.get('callbackUrl');
            var password = this.route.snapshot.queryParamMap.get('password');
            var user = this.route.snapshot.queryParamMap.get('user');
            this.fingerprintService.activateFaceID(user, password).then(function () {
                _this.navCntrl.navigateForward(callbackUrl);
            });
        };
        BiometricActivator.prototype.activateTouchID = function () {
            var _this = this;
            var callbackUrl = this.route.snapshot.queryParamMap.get('callbackUrl');
            var password = this.route.snapshot.queryParamMap.get('password');
            var user = this.route.snapshot.queryParamMap.get('user');
            this.fingerprintService.activateTouchID(user, password).then(function () {
                _this.navCntrl.navigateForward(callbackUrl);
            });
        };
        return BiometricActivator;
    }());
    BiometricActivator.decorators = [
        { type: core.Component, args: [{
                    selector: 'app-biometric-activator',
                    template: "<ion-content class=\"ion-padding-horizontal\">\r\n    <ion-icon class=\"close-btn\" name=\"close-outline\" color=\"secondary\" (click)=\"close()\"></ion-icon>\r\n    <ion-grid *ngIf=\"biometrics$ | async as biometrics\" class=\"p-0\">\r\n  \r\n        <!-- IF FACEID AND NOT TOUCHID -->\r\n        <ng-container *ngIf=\"biometrics.face && !biometrics.touch\">\r\n            <ion-row>\r\n                <ion-col class=\"px-5\">\r\n                    <h1 class=\"ion-text-left mt-5\">{{ 'LOGIN-FACEID'| translate }}</h1>\r\n                    <span class=\"my-4\">{{ 'FACEID-NOT-SETTED'| translate }}</span><br/>\r\n                </ion-col>\r\n            </ion-row>\r\n            <ion-row >\r\n                <ion-col>\r\n                    <img class=\"icon-bio\" src=\"/assets/icon/face-id-bio.svg\" />\r\n                </ion-col>\r\n            </ion-row>\r\n        \r\n            <ion-button class=\"btn\" color=\"primary\" (click)=\"activateFaceID()\">\r\n                {{ 'FACEID-SET' | translate }}\r\n            </ion-button>\r\n        </ng-container>\r\n        <!-- END IF FACEID -->\r\n  \r\n        <!-- IF TOUCHID -->\r\n        <ng-container *ngIf=\"biometrics.touch\">\r\n            <ion-row>\r\n                <ion-col class=\"px-5\">\r\n                <h1 class=\"ion-text-left mt-5\">{{ 'LOGIN-TOUCH-ID'| translate }}</h1>\r\n                <p class=\"my-4\">{{ 'TOUCH-ID-NOT-SETTED'| translate }}</p>\r\n                </ion-col>\r\n            </ion-row>\r\n    \r\n            <ion-row>\r\n                <ion-col>\r\n                    <img class=\"icon-bio\" src=\"/assets/icon/Icon_Touch_ID-bio.svg\" />\r\n                </ion-col>\r\n            </ion-row>\r\n    \r\n            <ion-button class=\"btn\" color=\"primary\" (click)=\"activateTouchID()\">\r\n                {{ 'TOUCH-ID-SET' | translate }}\r\n            </ion-button>\r\n        </ng-container>\r\n        <!-- END IF TOUCHID -->\r\n  \r\n    </ion-grid>\r\n</ion-content>  ",
                    changeDetection: core.ChangeDetectionStrategy.OnPush,
                    styles: ["ion-content{--padding-start: 0;--padding-end: 0}ion-grid{height:100%;display:flex;flex-direction:column;justify-content:space-between}ion-content h1{font-size:1.6em!important}ion-content p{font-size:1.6m!important}img{position:absolute;left:0;right:0;margin:0 auto;top:50%;bottom:50%;transform:translateY(-50%);height:15vh;fill:#c4c8cb!important}\n"]
                },] }
    ];
    BiometricActivator.ctorParameters = function () { return [
        { type: angular.NavController },
        { type: router.ActivatedRoute },
        { type: FingerprintService }
    ]; };

    var routes = [
        {
            path: '',
            component: BiometricActivator
        }
    ];
    var BiometricActivatorPageRoutingModule = /** @class */ (function () {
        function BiometricActivatorPageRoutingModule() {
        }
        return BiometricActivatorPageRoutingModule;
    }());
    BiometricActivatorPageRoutingModule.decorators = [
        { type: core.NgModule, args: [{
                    imports: [router.RouterModule.forChild(routes)],
                    exports: [router.RouterModule]
                },] }
    ];

    var BiometricActivatorModule = /** @class */ (function () {
        function BiometricActivatorModule() {
        }
        return BiometricActivatorModule;
    }());
    BiometricActivatorModule.decorators = [
        { type: core.NgModule, args: [{
                    imports: [
                        common.CommonModule,
                        forms.ReactiveFormsModule,
                        core$1.TranslateModule,
                        angular.IonicModule,
                        BiometricActivatorPageRoutingModule
                    ],
                    declarations: [BiometricActivator]
                },] }
    ];

    /*
     * Public API Surface of fingerprint-auth
     */

    /**
     * Generated bundle index. Do not edit.
     */

    exports.BiometricActivator = BiometricActivator;
    exports.BiometricActivatorModule = BiometricActivatorModule;
    exports.BiometricActivatorPageRoutingModule = BiometricActivatorPageRoutingModule;
    exports.BiometricLoginActivePipe = BiometricLoginActivePipe;
    exports.FingerprintAuthModule = FingerprintAuthModule;
    exports.FingerprintService = FingerprintService;
    exports["ɵa"] = Config;
    exports["ɵb"] = StorageService;

    Object.defineProperty(exports, '__esModule', { value: true });

}));
//# sourceMappingURL=phemium-costaisa-fingerprint-auth.umd.js.map