Skip to content

Commit 7cdb4ea

Browse files
Added a second method so you can now choose between fallback to passcode and a custom one.
1 parent f8848a1 commit 7cdb4ea

File tree

5 files changed

+71
-47
lines changed

5 files changed

+71
-47
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ Want a nicer guide than these raw code samples? Read [Nic Raboy's blog post abou
3535

3636
```js
3737
touchid.verifyFingerprint({
38+
message: 'Scan yer finger' // optional, shown in the fingerprint dialog (default: 'Scan your finger').
39+
}).then(
40+
function() {
41+
console.log("Fingerprint was OK");
42+
},
43+
function(error) {
44+
console.log("Fingerprint NOT OK" + (error.code ? ". Code: " + error.code : ""));
45+
}
46+
)
47+
```
48+
49+
### function: verifyFingerprintWithCustomFallback
50+
51+
```js
52+
touchid.verifyFingerprintWithCustomFallback({
3853
message: 'Scan yer finger', // optional, shown in the fingerprint dialog (default: 'Scan your finger').
3954
fallbackMessage: 'Enter PIN' // optional, the button label when scanning fails (default: 'Enter password').
4055
}).then(
@@ -48,5 +63,6 @@ Want a nicer guide than these raw code samples? Read [Nic Raboy's blog post abou
4863
```
4964

5065
## Changelog
66+
1.2.0 You can now use the built-in passcode interface as fallback.
5167
1.1.1 Added TypeScript definitions.
5268
1.1.0 Added Android platform which will always return false for `touchid.available`.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"name": "nativescript-touchid",
3-
"version": "1.1.1",
3+
"version": "2.0.0",
44
"description": "A TouchID (fingerprint scanner) module for use in NativeScript apps",
55
"main": "touchid.js",
66
"nativescript": {
77
"platforms": {
8-
"android": "1.4.0",
9-
"ios": "1.4.0"
8+
"android": "1.7.0",
9+
"ios": "1.7.0"
1010
}
1111
},
1212
"repository": {

touchid.android.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,10 @@ exports.verifyFingerprint = function () {
88
return new Promise(function (resolve, reject) {
99
reject("Not available");
1010
});
11+
};
12+
13+
exports.verifyFingerprintWithCustomFallback = function () {
14+
return new Promise(function (resolve, reject) {
15+
reject("Not available");
16+
});
1117
};

touchid.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ declare module "nativescript-touchid" {
2323
* Gets any currently present text from the clipboard.
2424
*/
2525
export function verifyFingerprint(options: VerifyFingerprintOptions): Promise<string>;
26+
export function verifyFingerprintWithCustomFallback(options: VerifyFingerprintOptions): Promise<string>;
2627
}

touchid.ios.js

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,54 @@ var available = function () {
1414
});
1515
};
1616

17+
/**
18+
* this 'default' method uses keychain instead of localauth so the passcode fallback can be used
19+
*/
1720
var verifyFingerprint = function (arg) {
21+
return new Promise(function (resolve, reject) {
22+
try {
23+
24+
if (keychainItemServiceName === null) {
25+
var bundleID = NSBundle.mainBundle().infoDictionary.objectForKey("CFBundleIdentifier");
26+
keychainItemServiceName = bundleID + ".TouchID";
27+
}
28+
29+
if (!createKeyChainEntry()) {
30+
verifyFingerprint(arg);
31+
} else {
32+
var message = arg !== null && arg.message || "Scan your finger";
33+
var query = NSMutableDictionary.alloc().init();
34+
query.setObjectForKey(kSecClassGenericPassword, kSecClass);
35+
query.setObjectForKey(keychainItemIdentifier, kSecAttrAccount);
36+
query.setObjectForKey(keychainItemServiceName, kSecAttrService);
37+
query.setObjectForKey(message, kSecUseOperationPrompt);
38+
39+
// Start the query and the fingerprint scan and/or device passcode validation
40+
var res = SecItemCopyMatching(query, null);
41+
if (res === 0) { // 0 = ok (match, not canceled)
42+
resolve();
43+
} else {
44+
reject(res);
45+
}
46+
}
47+
48+
} catch (ex) {
49+
console.log("Error in touchid.verifyFingerprint: " + ex);
50+
reject(ex);
51+
}
52+
});
53+
};
54+
55+
/**
56+
* This implementation uses LocalAuthentication and has no built-in passcode fallback
57+
*/
58+
var verifyFingerprintWithCustomFallback = function (arg) {
1859
return new Promise(function (resolve, reject) {
1960
try {
2061
var laContext = LAContext.alloc().init();
2162
if (laContext.canEvaluatePolicyError(LAPolicyDeviceOwnerAuthenticationWithBiometrics, null)) {
22-
var message = arg != null && arg.message || "Scan your finger";
23-
if (arg != null && arg.fallbackMessage) {
63+
var message = arg !== null && arg.message || "Scan your finger";
64+
if (arg !== null && arg.fallbackMessage) {
2465
laContext.localizedFallbackTitle = arg.fallbackMessage;
2566
}
2667
laContext.evaluatePolicyLocalizedReasonReply(
@@ -44,46 +85,6 @@ var verifyFingerprint = function (arg) {
4485
});
4586
};
4687

47-
var verifyFingerprintWithPasscodeFallback = function (arg) {
48-
return new Promise(function (resolve, reject) {
49-
try {
50-
51-
if (keychainItemServiceName == null) {
52-
var bundleID = NSBundle.mainBundle().infoDictionary.objectForKey("CFBundleIdentifier");
53-
keychainItemServiceName = bundleID + ".TouchID";
54-
console.log("---- keychainItemServiceName " + keychainItemServiceName);
55-
}
56-
57-
if (!createKeyChainEntry()) {
58-
console.log("Keychain trouble. Falling back to verifyFingerprintWithCustomPasswordFallback.");
59-
verifyFingerprintWithCustomPasswordFallback(arg);
60-
} else {
61-
62-
var message = arg != null && arg.message || "Scan your finger";
63-
console.log("message: " + message);
64-
65-
var query = NSMutableDictionary.alloc().init();
66-
query.setObjectForKey(kSecClassGenericPassword, kSecClass);
67-
query.setObjectForKey(keychainItemIdentifier, kSecAttrAccount);
68-
query.setObjectForKey(keychainItemServiceName, kSecAttrService);
69-
query.setObjectForKey(message, kSecUseOperationPrompt);
70-
71-
console.log("query: " + query);
72-
73-
// Start the query and the fingerprint scan and/or device passcode validation
74-
var res = SecItemCopyMatching(query, null);
75-
console.log("res: " + res); // 0 = noErr
76-
resolve(res == noErr);
77-
}
78-
//}
79-
80-
} catch (ex) {
81-
console.log("Error in touchid.verifyFingerprint: " + ex);
82-
reject(ex);
83-
}
84-
});
85-
};
86-
8788
var createKeyChainEntry = function () {
8889
var attributes = NSMutableDictionary.alloc().init();
8990
attributes.setObjectForKey(kSecClassGenericPassword, kSecClass);
@@ -97,7 +98,7 @@ var createKeyChainEntry = function () {
9798
kSecAccessControlUserPresence,
9899
null
99100
);
100-
if (accessControlRef == null) {
101+
if (accessControlRef === null) {
101102
console.log("Can't store identifier '" + keychainItemIdentifier + "' in the KeyChain: " + accessControlError + ".");
102103
return false;
103104
} else {
@@ -117,4 +118,4 @@ var createKeyChainEntry = function () {
117118

118119
exports.available = available;
119120
exports.verifyFingerprint = verifyFingerprint;
120-
exports.verifyFingerprintWithPasscodeFallback = verifyFingerprintWithPasscodeFallback;
121+
exports.verifyFingerprintWithCustomFallback = verifyFingerprintWithCustomFallback;

0 commit comments

Comments
 (0)