UNPKG

nativescript-fingerprint-auth-custom

Version:

Fork from nativescript-fingerprint-auth to implement custom Android Screen. fingerprint authentication plugin for use in NativeScript apps

258 lines (257 loc) 12.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var app = require("tns-core-modules/application"); var utils_1 = require("tns-core-modules/utils/utils"); var fingerprint_auth_common_1 = require("./fingerprint-auth.common"); var KEY_NAME = "fingerprintauth"; var SECRET_BYTE_ARRAY = Array.create("byte", 16); var REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 788; var FingerprintAuth = (function () { function FingerprintAuth() { this.keyguardManager = utils_1.ad .getApplicationContext() .getSystemService("keyguard"); } FingerprintAuth.prototype.available = function () { var _this = this; return new Promise(function (resolve, reject) { try { if (!_this.keyguardManager || !_this.keyguardManager.isKeyguardSecure()) { resolve({ any: false }); return; } if (android.os.Build.VERSION.SDK_INT < 23) { reject("Your api version doesn't support fingerprint authentication"); return; } var fingerprintManager = utils_1.ad .getApplicationContext() .getSystemService("fingerprint"); if (!fingerprintManager.isHardwareDetected()) { reject("Device doesn't support fingerprint authentication"); } else if (!fingerprintManager.hasEnrolledFingerprints()) { if (_this.keyguardManager.isDeviceSecure()) { resolve({ any: true, touch: false }); } else { reject("User hasn't enrolled any fingerprints to authenticate with"); } } else { resolve({ any: true, touch: true }); } } catch (ex) { console.log("fingerprint-auth.available: " + ex); reject(ex); } }); }; FingerprintAuth.prototype.didFingerprintDatabaseChange = function () { return new Promise(function (resolve, reject) { resolve(false); }); }; FingerprintAuth.prototype.verifyWithCustomAndroidUI = function (resolve, reject, authenticationCallback) { this.fingerPrintManager.authenticate(authenticationCallback, this.getActivity().getSupportFragmentManager()); }; FingerprintAuth.prototype.verifyFingerprint = function (options) { var _this = this; return new Promise(function (resolve, reject) { try { var hasSupportFragment = _this.getActivity().getSupportFragmentManager !== undefined; if (options.useCustomAndroidUI && !hasSupportFragment) { reject({ code: fingerprint_auth_common_1.ERROR_CODES.DEVELOPER_ERROR, message: "Custom Fingerprint UI requires changes to AndroidManifest.xml. See the nativescript-fingerprint-auth documentation." }); } else if (options.useCustomAndroidUI && hasSupportFragment) { if (!_this.fingerPrintManager) { _this.fingerPrintManager = new com.jesusm.kfingerprintmanager.KFingerprintManager(utils_1.ad.getApplicationContext(), KEY_NAME); } var that_1 = _this; var callback = new com.jesusm.kfingerprintmanager.KFingerprintManager.AuthenticationCallback({ attempts: 0, onAuthenticationFailedWithHelp: function (help) { var _this = this; if (++this.attempts < 3) { setTimeout(function () { return that_1.verifyWithCustomAndroidUI(resolve, reject, _this); }, 50); } else { reject({ code: fingerprint_auth_common_1.ERROR_CODES.RECOVERABLE_ERROR, message: help }); } }, onAuthenticationSuccess: function () { resolve(); }, onSuccessWithManualPassword: function (password) { resolve(password); }, onFingerprintNotRecognized: function () { var _this = this; if (++this.attempts < 3) { setTimeout(function () { return that_1.verifyWithCustomAndroidUI(resolve, reject, _this); }, 50); } else { reject({ code: fingerprint_auth_common_1.ERROR_CODES.NOT_RECOGNIZED, message: "Fingerprint not recognized." }); } }, onFingerprintNotAvailable: function () { reject({ code: fingerprint_auth_common_1.ERROR_CODES.NOT_CONFIGURED, message: 'Secure lock screen hasn\'t been set up.\n Go to "Settings -> Security -> Screenlock" to set up a lock screen.' }); }, onCancelled: function () { reject({ code: fingerprint_auth_common_1.ERROR_CODES.PASSWORD_FALLBACK_SELECTED, message: "Cancelled by user" }); } }); _this.verifyWithCustomAndroidUI(resolve, reject, callback); } else { var onActivityResult_1 = function (data) { if (data.requestCode === REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) { if (data.resultCode === android.app.Activity.RESULT_OK) { resolve(); } else { reject({ code: fingerprint_auth_common_1.ERROR_CODES.USER_CANCELLED, message: "User cancelled." }); } } app.android.off(app.AndroidApplication.activityResultEvent, onActivityResult_1); }; app.android.on(app.AndroidApplication.activityResultEvent, onActivityResult_1); if (!_this.keyguardManager) { reject({ code: fingerprint_auth_common_1.ERROR_CODES.NOT_AVAILABLE, message: "Keyguard manager not available." }); } if (_this.keyguardManager && !_this.keyguardManager.isKeyguardSecure()) { reject({ code: fingerprint_auth_common_1.ERROR_CODES.NOT_CONFIGURED, message: 'Secure lock screen hasn\'t been set up.\n Go to "Settings -> Security -> Screenlock" to set up a lock screen.' }); } FingerprintAuth.createKey(options); var tryEncryptResult = _this.tryEncrypt(options); if (tryEncryptResult === undefined) { } else if (tryEncryptResult === true) { resolve(); } else { reject({ code: fingerprint_auth_common_1.ERROR_CODES.UNEXPECTED_ERROR, message: "See the console for error logs." }); } } } catch (ex) { console.log("Error in fingerprint-auth.verifyFingerprint: " + ex); reject({ code: fingerprint_auth_common_1.ERROR_CODES.UNEXPECTED_ERROR, message: ex }); } }); }; FingerprintAuth.prototype.verifyFingerprintWithCustomFallback = function (options) { return this.verifyFingerprint(options); }; FingerprintAuth.prototype.close = function () { var fragmentManager = this.getActivity().getSupportFragmentManager(); var fragmentTag = "KFingerprintManager:fingerprintDialog"; var fragment = fragmentManager.findFragmentByTag(fragmentTag); if (fragment) { fragmentManager.beginTransaction().remove(fragment).commit(); } else { } }; FingerprintAuth.createKey = function (options) { try { var keyStore = java.security.KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); var keyGenerator = javax.crypto.KeyGenerator.getInstance(android.security.keystore.KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); keyGenerator.init(new android.security.keystore.KeyGenParameterSpec.Builder(KEY_NAME, android.security.keystore.KeyProperties.PURPOSE_ENCRYPT | android.security.keystore.KeyProperties.PURPOSE_DECRYPT) .setBlockModes([ android.security.keystore.KeyProperties.BLOCK_MODE_CBC ]) .setUserAuthenticationRequired(true) .setUserAuthenticationValidityDurationSeconds(options && options.authenticationValidityDuration ? options.authenticationValidityDuration : 5) .setEncryptionPaddings([ android.security.keystore.KeyProperties.ENCRYPTION_PADDING_PKCS7 ]) .build()); keyGenerator.generateKey(); } catch (error) { if (("" + error.nativeException).indexOf("java.security.NoSuchAlgorithmException:") > -1) { } } }; FingerprintAuth.prototype.tryEncrypt = function (options) { try { var keyStore = java.security.KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); var secretKey = keyStore.getKey(KEY_NAME, null); var cipher = javax.crypto.Cipher.getInstance(android.security.keystore.KeyProperties.KEY_ALGORITHM_AES + "/" + android.security.keystore.KeyProperties.BLOCK_MODE_CBC + "/" + android.security.keystore.KeyProperties.ENCRYPTION_PADDING_PKCS7); cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey); cipher.doFinal(SECRET_BYTE_ARRAY); return true; } catch (error) { if (("" + error.nativeException).indexOf("android.security.keystore.UserNotAuthenticatedException") > -1) { this.showAuthenticationScreen(options); return undefined; } else if (("" + error.nativeException).indexOf("android.security.keystore.KeyPermanentlyInvalidatedException") > -1) { console.log(error); } else { console.log(error); } return false; } }; FingerprintAuth.prototype.showAuthenticationScreen = function (options) { var intent = this .keyguardManager.createConfirmDeviceCredentialIntent(options && options.title ? options.title : null, options && options.message ? options.message : null); if (intent !== null) { this.getActivity().startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS); } }; FingerprintAuth.prototype.getActivity = function () { return app.android.foregroundActivity || app.android.startActivity; }; return FingerprintAuth; }()); exports.FingerprintAuth = FingerprintAuth;