@nativescript/biometrics
npm install @nativescript/biometrics
Replaces @nativescript/fingerprint-auth
This plugin replaces @nativescript/fingerprint-auth
API
Android Compatibility: API 23+
available
JavaScript
var biometricAuthPlugin = require('@nativescript/biometrics');
var biometricAuth = new biometricAuthPlugin.BiometricAuth();
biometricAuth.available().then(function (avail) {
console.log('Available? ' + avail);
});
TypeScript
import { BiometricAuth, BiometricIDAvailableResult } from "@nativescript/biometrics";
class MyClass {
private biometricAuth: BiometricAuth;
constructor() {
this.biometricAuth = new BiometricAuth();
}
this.biometricAuth.available().then((result: BiometricIDAvailableResult) => {
console.log(`Biometric ID available? ${result.any}`);
console.log(`Touch? ${result.touch}`);
console.log(`Face? ${result.face}`);
console.log(`Biometrics? ${result.biometrics}`);
});
}
verifyBiometric
Note that on the iOS simulator use Features->Face ID menu items to enroll a face and signal successs/failure to recognize a face.
verifyBiometric will fail on IOS simulator unless pinfallBack is used.
biometricAuth
.verifyBiometric({
title: 'Android title',
message: 'Scan yer finger',
fallbackMessage: 'Enter your PIN',
pinFallback: true,
})
.then((result?: BiometricResult) => {
if (result.code === ERROR_CODES.SUCCESS) {
console.log('Biometric ID OK');
}
})
.catch((err) => console.log(`Biometric ID NOT OK: ${JSON.stringify(err)}`));
Face ID (iOS)
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>
Security++ (iOS)
Since iOS9 it's possible to check whether or not the list of enrolled fingerprints changed since
the last time you checked it. It's recommended you add this check so you can counter hacker attacks
to your app. See this article for more details.
So instead of checking the fingerprint after available
add another check.
In case didFingerprintDatabaseChange
returns true
you probably want to re-authenticate your user
before accepting valid fingerprints again.
biometricAuth.available().then((avail) => {
if (!avail) {
return;
}
biometricAuth.didFingerprintDatabaseChange().then((changed) => {
if (changed) {
} else {
}
});
});
Biometrics and cryptography
Normal operation
If you do not pass any of the options (pinFallback / keyName) to the verify method then the plugin will create a secure key, call the authorization methods to trigger face/fingerprint and then attempt to use the key to encrypt some text. The idea being that the key will not be accessible unless the user has successfully authenticated.
This however is not foolproof and the most secure method is to pass the secret
and Keyname
options to encrypt/decrypt text.
Encrypting/Decrypting with Authentication
The best practice is to use the options to encrypt some secret that is validated independently, this is more secure because the key used for decryption cannot be accessed without proper authentication, therefor your secret cannot be decrypted properly.
-
Encrypt your secret
Call verifyBiometric
with the relevant properties.
biometricAuth
.verifyBiometric({
title: 'Enter your password',
message: 'Scan yer finger',
pinFallback: false,
keyName: 'MySecretKeyName',
secret: 'The Secret I want encrypted',
})
.then((result) => {
const encryptedText = result.encrypted;
const IV = result.iv;
})
.catch((err) => this.set('status', `Biometric ID NOT OK: " + ${JSON.stringify(err)}`));
For Android the encrypted result and vector would then be stored in your app and used the next time the user logged in be calling the verifyBiometric
again:
-
Decrypt your secret
biometricAuth
.verifyBiometric({
title: 'Enter your password',
message: 'Scan yer finger',
keyName: 'MySecretKeyName',
pinFallback: false,
android: {
decryptText: 'The encrypted text retrieved previously',
iv: 'The IV retrieved previously',
},
ios: { fetchSecret: true },
})
.then((result) => {
const decryptedText = result.decrypted;
verifyMySecret(decryptedText);
})
.catch((err) => this.set('status', `Biometric ID NOT OK: " + ${JSON.stringify(err)}`));
Fallback to Pin
Allowing the user to fallback on lock screen credentials ( pin etc. ) disables cryptography.
Also on android for phones running API < 30 only fingerprint is used, because the old fingerprint api is called.
e.g.
biometricAuth
.verifyBiometric({
title: 'Enter your password',
message: 'Scan yer finger',
fallbackMessage: 'Enter PIN',
pinFallback: true,
ios: { customFallback: false },
})
.then((result) => {
console.log('Fingerprint/ PIN was OK');
})
.catch((err) => this.set('status', `Biometric ID NOT OK: " + ${JSON.stringify(err)}`));
License
Apache License Version 2.0