Also works with Face ID on iPhone X Requires Xcode 9+, iOS 11 SDK
From the command prompt go to your app's root folder and execute:
tns plugin add nativescript-keystore-access
You must always make sure you call cleanup()
when you leave/finish the context where you are using the plugin. This is because of the way the Android FingerprintManager works. If you have the Android FingerprintManager listening for fingerprint and you leave the context or even closes the app or crash the app, you may have a defunct FingerprintManager still listening for fingerprint, and then if you start the app again or any other app that uses fingerprint, this will fail because of the still listening defunct FingerprintManager. It is therefore important to hook into ngOnDestroy()
on any component using this plugin an call cleanup()
here.
Call this method to check if biometrics is available on your device. Always call this method and check the result before calling any other method.
import { KeystoreAccess, BiometricIDAvailableResult } from "nativescript-keystore-access";
class MyClass {
private keystoreAccess: KeystoreAccess;
constructor() {
this.keystoreAccess = new KeystoreAccess();
}
this.keystoreAccess.available().then((result: BiometricIDAvailableResult) => {
console.log(`Biometric ID available? ${result.any}`);
console.log(`Touch? ${result.touch}`);
console.log(`Face? ${result.face}`);
if (result.customUI) {
// You must show a custom biometrics UI, basicly this means you are on Android and the OS does not show a UI for you.
// You can at any time call `useCustomUI` to check if you should show a custom biometrics UI.
}
}).catch(err => {
console.log("doCheckAvailable error: " + err.code + ", " + err.message);
});
}
Call this method to check if you must show a custom biometrics UI to inform the user that the device is witing for a fingerprint.
import { KeystoreAccess } from "nativescript-keystore-access";
class MyClass {
private keystoreAccess: KeystoreAccess;
constructor() {
this.keystoreAccess = new KeystoreAccess();
}
if (this.keystoreAccess.useCustomUI()) {
// You must show a custom biometrics UI, basicly this means you are on Android and the OS does not show a UI for you.
// You can at any time call `useCustomUI` to check if you should show a custom biometrics UI.
}
}
Call this method to have some string
data encrypted with the device keystore in a way so that it can only be decrypted with biometrics authentication.
import { KeystoreAccess } from "nativescript-keystore-access";
class MyClass {
private keystoreAccess: KeystoreAccess;
constructor() {
this.keystoreAccess = new KeystoreAccess();
}
// Remember to call "useCustomUI()" and show some UI that is indicating to the user that the device is awaiting a fingerprint.
this.keystoreAccess.storeDataWithFingerprint(
keystoreKeyAlias: "ALIAS", // A unique id for your data, use the same key for encryption and decryption of the same data, and another key for different data.
data: "This is a secret", // The string you want to encrypt and store.
biometricMessage: "Biometric Message" // A short description that will show up on the iOS biometrics dialog.
).then((result: void) => {
console.log("Your secret is safe with me");
// You can now remove your custom biometrics UI
}).catch(err => {
console.log("storeDataWithFingerprint error: " + err.code + ", " + err.message);
// Inform the user of the error, that may or may not be recoverable, on your custom biometrics UI
});
}
Call this method to retrieve previously encrypted and stored data as a decrypted string
.
import { KeystoreAccess } from "nativescript-keystore-access";
class MyClass {
private keystoreAccess: KeystoreAccess;
constructor() {
this.keystoreAccess = new KeystoreAccess();
}
// Remember to call "useCustomUI()" and show some UI that is indicating to the user that the device is awaiting a fingerprint.
this.keystoreAccess.retrieveDataWithFingerprint(
keystoreKeyAlias: "ALIAS", // A unique id for your data, use the same key for encryption and decryption of the same data, and another key for different data.
biometricPromptMessage: "Biometric Prompt Message" // A short description that will show up on the iOS biometrics dialog.
).then((result: string) => {
console.log("I just unlocked your secret: " + result);
// You can now remove your custom biometrics UI
}).catch(err => {
console.log("retrieveDataWithFingerprint error: " + err.code + ", " + err.message);
// Inform the user of the error, that may or may not be recoverable, on your custom biometrics UI
});
}
Call this method to check if you have encrypted data stored on this device.
import { KeystoreAccess } from "nativescript-keystore-access";
class MyClass {
private keystoreAccess: KeystoreAccess;
constructor() {
this.keystoreAccess = new KeystoreAccess();
}
if (this.keystoreAccess.fingerprintEncryptedDataExists(
keystoreKeyAlias: "ALIAS" // A unique id for your data, use the same key for encryption and decryption of the same data, and another key for different data.
)) {
console.log("You have encrypted data store on this device, go ahead and retrieve it if you like");
)
}
Call this method to delete any existing encrypted data stored on this device.
import { KeystoreAccess } from "nativescript-keystore-access";
class MyClass {
private keystoreAccess: KeystoreAccess;
constructor() {
this.keystoreAccess = new KeystoreAccess();
}
this.keystoreAccess.deleteFingerprintEncryptedData(
keystoreKeyAlias: "ALIAS" // A unique id for your data, use the same key for encryption and decryption of the same data, and another key for different data.
);
}
The iOS and Android biometrics SDK are very different and reports errors very differently. To make the usage of this plugin predictable without knowing what platform you are on, all error types have been mapped to one common finite list of error codes. The error codes are the following:
enum ERROR_CODES {
RECOVERABLE_ERROR_BIOMETRICS_NOT_RECOGNIZED = 102, // Biometrics are working and configured correctly, but the biometric input was not recognized
RECOVERABLE_ERROR_FINGER_MOVED_TO_FAST = 102, // Finger moved to fast on the fingerprint sensor (only Android)
RECOVERABLE_ERROR_FINGER_MUST_COVER_SENSOR = 101, // Finger must cover entire sensor (only Android)
DEVELOPER_ERROR = 10, // Unexpected error, report to maintainer of plugin please
NOT_AVAILABLE = 20, // Biometrics are not available on device
TAMPERED_WITH = -5, // Biometrics was changed (added or removed) since last successful authentication, maybe a hacker was on your device
AUTHENTICATION_FAILED = -1, // Biometrics are working and configured correctly, but the biometric input was not recognized
CANCEL = -2 // Biometric authentication was canceled, probably by user
}
iOS 11 added support for Face ID and was first supported by the iPhone X.
The developer needs to provide a value for NSFaceIDUsageDescription
, otherwise your app may crash.
You can provide this value (the reason for using Face ID) by adding something like this to app/App_Resources/ios/Info.plist
:
<key>NSFaceIDUsageDescription</key>
<string>For easy authentication with our app.</string>
This software is available under the MIT license.