@aparajita/capacitor-biometric-auth 3.1.4 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -7
- package/android/build.gradle +13 -11
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/java/com/aparajita/capacitor/biometricauth/AuthActivity.java +0 -4
- package/android/src/main/java/com/aparajita/capacitor/biometricauth/BiometricAuthNative.java +9 -2
- package/dist/esm/definitions.d.ts +26 -13
- package/dist/esm/definitions.js +14 -13
- package/dist/esm/index.js +1 -3
- package/dist/esm/native.js +3 -2
- package/dist/esm/web-utils.js +1 -1
- package/dist/esm/web.js +2 -1
- package/dist/plugin.cjs.js +20 -25
- package/dist/plugin.js +20 -25
- package/ios/Plugin/Plugin.m +0 -2
- package/ios/Plugin/Plugin.swift +21 -16
- package/package.json +28 -30
- package/dist/esm/info.json +0 -4
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ The API is extensively documented in the [TypeScript definitions file](src/defin
|
|
|
32
32
|
|
|
33
33
|
### Checking availability
|
|
34
34
|
|
|
35
|
-
Before giving the user the option to use biometry (such as displaying a biometry icon), call [`checkBiometry`](#checkbiometry) and inspect the [`CheckBiometryResult`](#checkbiometryresult) to see what (if any) biometry is available on the device. Note that `isAvailable` may be `false` but `biometryType` may indicate the presence of biometry on the device. This occurs if the current user is not enrolled in biometry, or if biometry has been disabled for the current app. In such cases the `reason` will tell you why.
|
|
35
|
+
Before giving the user the option to use biometry (such as displaying a biometry icon), call [`checkBiometry`](#checkbiometry) and inspect the [`CheckBiometryResult`](#checkbiometryresult) to see what (if any) biometry is available on the device. Note that `isAvailable` may be `false` but `biometryType` may indicate the presence of biometry on the device. This occurs if the current user is not enrolled in biometry, or if biometry has been disabled for the current app. In such cases the `reason` and `code` will tell you why.
|
|
36
36
|
|
|
37
37
|
Because the availability of biometry can change while your app is in the background, it’s important to check availability when your app resumes. By calling [`addResumeListener`](#addresumelistener) you can register a callback that is passed a [`CheckBiometryResult`](#checkbiometryresult) when your app resumes.
|
|
38
38
|
|
|
@@ -109,7 +109,7 @@ web only<br><br>On the web, this method allows you to dynamically simulate diffe
|
|
|
109
109
|
authenticate(options?: AuthenticateOptions) => Promise<void>
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
Prompt the user for authentication. If authorization fails for any reason, the promise is rejected with a `BiometryError`.<br><br>For detailed information about the behavior on iOS, see:<br><br>https://developer.apple.com/documentation/localauthentication/lapolicy/deviceownerauthenticationwithbiometrics<br><br>Some versions of Android impose a limit on the number of failed attempts. If `allowDeviceCredential` is `true`, when the limit is reached the user will then be presented with a device credential prompt. If `allowDeviceCredential` is `false`, when the limit is reached `authenticate()` will reject with a
|
|
112
|
+
Prompt the user for authentication. If authorization fails for any reason, the promise is rejected with a `BiometryError`.<br><br>For detailed information about the behavior on iOS, see:<br><br>https://developer.apple.com/documentation/localauthentication/lapolicy/deviceownerauthenticationwithbiometrics<br><br>Some versions of Android impose a limit on the number of failed attempts. If `allowDeviceCredential` is `true`, when the limit is reached the user will then be presented with a device credential prompt. If `allowDeviceCredential` is `false`, when the limit is reached `authenticate()` will reject with a <a href="#biometryerrortype">`BiometryErrorType`</a> of `biometryLockout`, after which the user will have to wait the system-defined length of time before being allowed to authenticate again.
|
|
113
113
|
|
|
114
114
|
| Param | Type |
|
|
115
115
|
| :------ | :----------------------------------------------------- |
|
|
@@ -137,11 +137,12 @@ Register a function that will be called when the app resumes. The function will
|
|
|
137
137
|
|
|
138
138
|
#### CheckBiometryResult
|
|
139
139
|
|
|
140
|
-
| Prop | Type
|
|
141
|
-
| :----------- |
|
|
142
|
-
| isAvailable | boolean
|
|
143
|
-
| biometryType | <a href="#biometrytype">BiometryType</a>
|
|
144
|
-
| reason | string
|
|
140
|
+
| Prop | Type | Description |
|
|
141
|
+
| :----------- | :------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
142
|
+
| isAvailable | boolean | True if the device has biometric authentication capability and the current user has enrolled in biometry. |
|
|
143
|
+
| biometryType | <a href="#biometrytype">BiometryType</a> | The type of biometry available on the device. |
|
|
144
|
+
| reason | string | If biometry is not available and the system gives a reason why, it will be returned here. Otherwise it's an empty string. |
|
|
145
|
+
| code | <a href="#biometryerrortype">BiometryErrorType</a> | If biometry is not available, the error code will be returned here. Otherwise it's an empty string. The error code will be one of the <a href="#biometryerrortype">`BiometryErrorType`</a> enum values, and is consistent across platforms. This allows you to check for specific errors in a platform- independent way, for example:<br><br>if (result.code === <a href="#biometryerrortype">BiometryErrorType.biometryNotEnrolled</a>) { ... } |
|
|
145
146
|
|
|
146
147
|
#### AuthenticateOptions
|
|
147
148
|
|
|
@@ -181,5 +182,23 @@ The signature of the callback passed to `addResumeListener()`.
|
|
|
181
182
|
| faceAuthentication | Android face authentication is available |
|
|
182
183
|
| irisAuthentication | Android iris authentication is available |
|
|
183
184
|
|
|
185
|
+
#### BiometryErrorType
|
|
186
|
+
|
|
187
|
+
| Members | Value |
|
|
188
|
+
| :------------------- | :--------------------- |
|
|
189
|
+
| none | '' |
|
|
190
|
+
| appCancel | 'appCancel' |
|
|
191
|
+
| authenticationFailed | 'authenticationFailed' |
|
|
192
|
+
| invalidContext | 'invalidContext' |
|
|
193
|
+
| notInteractive | 'notInteractive' |
|
|
194
|
+
| passcodeNotSet | 'passcodeNotSet' |
|
|
195
|
+
| systemCancel | 'systemCancel' |
|
|
196
|
+
| userCancel | 'userCancel' |
|
|
197
|
+
| userFallback | 'userFallback' |
|
|
198
|
+
| biometryLockout | 'biometryLockout' |
|
|
199
|
+
| biometryNotAvailable | 'biometryNotAvailable' |
|
|
200
|
+
| biometryNotEnrolled | 'biometryNotEnrolled' |
|
|
201
|
+
| noDeviceCredential | 'noDeviceCredential' |
|
|
202
|
+
|
|
184
203
|
</docgen-api>
|
|
185
204
|
</div>
|
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
ext {
|
|
2
2
|
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
|
|
5
6
|
}
|
|
6
7
|
|
|
7
8
|
buildscript {
|
|
@@ -10,17 +11,18 @@ buildscript {
|
|
|
10
11
|
mavenCentral()
|
|
11
12
|
}
|
|
12
13
|
dependencies {
|
|
13
|
-
classpath 'com.android.tools.build:gradle:
|
|
14
|
+
classpath 'com.android.tools.build:gradle:8.0.2'
|
|
14
15
|
}
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
apply plugin: 'com.android.library'
|
|
18
19
|
|
|
19
20
|
android {
|
|
20
|
-
|
|
21
|
+
namespace "com.aparajita.capacitor.biometricauth"
|
|
22
|
+
compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 33
|
|
21
23
|
defaultConfig {
|
|
22
24
|
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
|
|
23
|
-
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion :
|
|
25
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 33
|
|
24
26
|
versionCode 1
|
|
25
27
|
versionName "1.0"
|
|
26
28
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
@@ -35,8 +37,8 @@ android {
|
|
|
35
37
|
abortOnError false
|
|
36
38
|
}
|
|
37
39
|
compileOptions {
|
|
38
|
-
sourceCompatibility JavaVersion.
|
|
39
|
-
targetCompatibility JavaVersion.
|
|
40
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
41
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -50,11 +52,11 @@ dependencies {
|
|
|
50
52
|
implementation 'androidx.biometric:biometric:1.1.0'
|
|
51
53
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
52
54
|
implementation project(':capacitor-android')
|
|
53
|
-
implementation 'androidx.appcompat:appcompat:1.
|
|
54
|
-
implementation 'com.google.android.material:material:1.
|
|
55
|
+
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
56
|
+
implementation 'com.google.android.material:material:1.9.0'
|
|
55
57
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
|
56
|
-
implementation 'androidx.navigation:navigation-fragment:2.
|
|
57
|
-
implementation 'androidx.navigation:navigation-ui:2.
|
|
58
|
+
implementation 'androidx.navigation:navigation-fragment:2.6.0'
|
|
59
|
+
implementation 'androidx.navigation:navigation-ui:2.6.0'
|
|
58
60
|
testImplementation "junit:junit:$junitVersion"
|
|
59
61
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
60
62
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
@@ -35,10 +35,6 @@ public class AuthActivity extends AppCompatActivity {
|
|
|
35
35
|
String title = intent.getStringExtra(BiometricAuthNative.TITLE);
|
|
36
36
|
String subtitle = intent.getStringExtra(BiometricAuthNative.SUBTITLE);
|
|
37
37
|
String description = intent.getStringExtra(BiometricAuthNative.REASON);
|
|
38
|
-
final int maxAttempts = intent.getIntExtra(
|
|
39
|
-
BiometricAuthNative.MAX_ATTEMPTS,
|
|
40
|
-
BiometricAuthNative.DEFAULT_MAX_ATTEMPTS
|
|
41
|
-
);
|
|
42
38
|
allowDeviceCredential = false;
|
|
43
39
|
|
|
44
40
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
package/android/src/main/java/com/aparajita/capacitor/biometricauth/BiometricAuthNative.java
CHANGED
|
@@ -120,17 +120,24 @@ public class BiometricAuthNative extends Plugin {
|
|
|
120
120
|
reason = "There is no biometric hardware on this device.";
|
|
121
121
|
break;
|
|
122
122
|
case BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
|
|
123
|
-
reason = "The user can
|
|
123
|
+
reason = "The user can’t authenticate because a security vulnerability has been discovered with one or more hardware sensors.";
|
|
124
124
|
break;
|
|
125
125
|
case BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED:
|
|
126
|
-
reason = "The user can
|
|
126
|
+
reason = "The user can’t authenticate because the specified options are incompatible with the current Android version.";
|
|
127
127
|
break;
|
|
128
128
|
case BiometricManager.BIOMETRIC_STATUS_UNKNOWN:
|
|
129
129
|
reason = "Unable to determine whether the user can authenticate.";
|
|
130
130
|
break;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
String errorCode = biometryErrorCodeMap.get(biometryResult);
|
|
134
|
+
|
|
135
|
+
if (errorCode == null) {
|
|
136
|
+
errorCode = "biometryNotAvailable";
|
|
137
|
+
}
|
|
138
|
+
|
|
133
139
|
ret.put("reason", reason);
|
|
140
|
+
ret.put("code", errorCode);
|
|
134
141
|
call.resolve(ret);
|
|
135
142
|
}
|
|
136
143
|
|
|
@@ -110,18 +110,19 @@ export interface AuthenticateOptions {
|
|
|
110
110
|
* for a description of each error code.
|
|
111
111
|
*/
|
|
112
112
|
export declare enum BiometryErrorType {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
113
|
+
none = "",
|
|
114
|
+
appCancel = "appCancel",
|
|
115
|
+
authenticationFailed = "authenticationFailed",
|
|
116
|
+
invalidContext = "invalidContext",
|
|
117
|
+
notInteractive = "notInteractive",
|
|
118
|
+
passcodeNotSet = "passcodeNotSet",
|
|
119
|
+
systemCancel = "systemCancel",
|
|
120
|
+
userCancel = "userCancel",
|
|
121
|
+
userFallback = "userFallback",
|
|
122
|
+
biometryLockout = "biometryLockout",
|
|
123
|
+
biometryNotAvailable = "biometryNotAvailable",
|
|
124
|
+
biometryNotEnrolled = "biometryNotEnrolled",
|
|
125
|
+
noDeviceCredential = "noDeviceCredential"
|
|
125
126
|
}
|
|
126
127
|
export interface ResultError extends PluginResultError {
|
|
127
128
|
code: string;
|
|
@@ -146,11 +147,23 @@ export interface CheckBiometryResult {
|
|
|
146
147
|
* it will be returned here. Otherwise it's an empty string.
|
|
147
148
|
*/
|
|
148
149
|
reason: string;
|
|
150
|
+
/**
|
|
151
|
+
* If biometry is not available, the error code will be returned here.
|
|
152
|
+
* Otherwise it's an empty string. The error code will be one of the
|
|
153
|
+
* `BiometryErrorType` enum values, and is consistent across
|
|
154
|
+
* platforms. This allows you to check for specific errors in a platform-
|
|
155
|
+
* independent way, for example:
|
|
156
|
+
*
|
|
157
|
+
* if (result.code === BiometryErrorType.biometryNotEnrolled) {
|
|
158
|
+
* ...
|
|
159
|
+
* }
|
|
160
|
+
*/
|
|
161
|
+
code: BiometryErrorType;
|
|
149
162
|
}
|
|
150
163
|
/**
|
|
151
164
|
* The signature of the callback passed to `addResumeListener()`.
|
|
152
165
|
*/
|
|
153
|
-
export
|
|
166
|
+
export type ResumeListener = (info: CheckBiometryResult) => void;
|
|
154
167
|
export interface BiometricAuthPlugin extends WebPlugin {
|
|
155
168
|
/**
|
|
156
169
|
* Check to see what biometry type (if any) is available.
|
package/dist/esm/definitions.js
CHANGED
|
@@ -35,22 +35,23 @@ export var BiometryType;
|
|
|
35
35
|
*/
|
|
36
36
|
export var BiometryErrorType;
|
|
37
37
|
(function (BiometryErrorType) {
|
|
38
|
-
BiometryErrorType[
|
|
39
|
-
BiometryErrorType[
|
|
40
|
-
BiometryErrorType[
|
|
41
|
-
BiometryErrorType[
|
|
42
|
-
BiometryErrorType[
|
|
43
|
-
BiometryErrorType[
|
|
44
|
-
BiometryErrorType[
|
|
45
|
-
BiometryErrorType[
|
|
46
|
-
BiometryErrorType[
|
|
47
|
-
BiometryErrorType[
|
|
48
|
-
BiometryErrorType[
|
|
49
|
-
BiometryErrorType[
|
|
38
|
+
BiometryErrorType["none"] = "";
|
|
39
|
+
BiometryErrorType["appCancel"] = "appCancel";
|
|
40
|
+
BiometryErrorType["authenticationFailed"] = "authenticationFailed";
|
|
41
|
+
BiometryErrorType["invalidContext"] = "invalidContext";
|
|
42
|
+
BiometryErrorType["notInteractive"] = "notInteractive";
|
|
43
|
+
BiometryErrorType["passcodeNotSet"] = "passcodeNotSet";
|
|
44
|
+
BiometryErrorType["systemCancel"] = "systemCancel";
|
|
45
|
+
BiometryErrorType["userCancel"] = "userCancel";
|
|
46
|
+
BiometryErrorType["userFallback"] = "userFallback";
|
|
47
|
+
BiometryErrorType["biometryLockout"] = "biometryLockout";
|
|
48
|
+
BiometryErrorType["biometryNotAvailable"] = "biometryNotAvailable";
|
|
49
|
+
BiometryErrorType["biometryNotEnrolled"] = "biometryNotEnrolled";
|
|
50
|
+
BiometryErrorType["noDeviceCredential"] = "noDeviceCredential";
|
|
50
51
|
})(BiometryErrorType || (BiometryErrorType = {}));
|
|
51
52
|
export class BiometryError {
|
|
52
53
|
constructor(message, code) {
|
|
53
54
|
this.message = message;
|
|
54
|
-
this.code =
|
|
55
|
+
this.code = code;
|
|
55
56
|
}
|
|
56
57
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { registerPlugin } from '@capacitor/core';
|
|
2
|
-
import info from './info.json';
|
|
3
|
-
console.log(`loaded ${info.name} v${info.version}`);
|
|
4
2
|
const proxy = registerPlugin('BiometricAuthNative', {
|
|
5
3
|
web: async () => import('./web').then((module) => new module.BiometricAuthWeb()),
|
|
6
4
|
ios: async () => import('./native').then((module) => new module.BiometricAuthNative(proxy)),
|
|
7
|
-
android: async () => import('./native').then((module) => new module.BiometricAuthNative(proxy))
|
|
5
|
+
android: async () => import('./native').then((module) => new module.BiometricAuthNative(proxy)),
|
|
8
6
|
});
|
|
9
7
|
export * from './definitions';
|
|
10
8
|
export * from './web-utils';
|
package/dist/esm/native.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BiometricAuthBase } from './base';
|
|
2
|
-
import { BiometryType } from './definitions';
|
|
2
|
+
import { BiometryErrorType, BiometryType } from './definitions';
|
|
3
3
|
// eslint-disable-next-line import/prefer-default-export
|
|
4
4
|
export class BiometricAuthNative extends BiometricAuthBase {
|
|
5
5
|
constructor(capProxy) {
|
|
@@ -12,7 +12,8 @@ export class BiometricAuthNative extends BiometricAuthBase {
|
|
|
12
12
|
return Promise.resolve({
|
|
13
13
|
isAvailable: true,
|
|
14
14
|
biometryType: BiometryType.none,
|
|
15
|
-
reason: ''
|
|
15
|
+
reason: '',
|
|
16
|
+
code: BiometryErrorType.none,
|
|
16
17
|
});
|
|
17
18
|
}
|
|
18
19
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
|
package/dist/esm/web-utils.js
CHANGED
|
@@ -5,7 +5,7 @@ const kBiometryTypeNameMap = {
|
|
|
5
5
|
[BiometryType.faceId]: 'Face ID',
|
|
6
6
|
[BiometryType.fingerprintAuthentication]: 'Fingerprint Authentication',
|
|
7
7
|
[BiometryType.faceAuthentication]: 'Face Authentication',
|
|
8
|
-
[BiometryType.irisAuthentication]: 'Iris Authentication'
|
|
8
|
+
[BiometryType.irisAuthentication]: 'Iris Authentication',
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
11
|
* Return a human-readable name for a BiometryType.
|
package/dist/esm/web.js
CHANGED
|
@@ -11,7 +11,8 @@ export class BiometricAuthWeb extends BiometricAuthBase {
|
|
|
11
11
|
return Promise.resolve({
|
|
12
12
|
isAvailable: this.biometryType !== BiometryType.none,
|
|
13
13
|
biometryType: this.biometryType,
|
|
14
|
-
reason: ''
|
|
14
|
+
reason: '',
|
|
15
|
+
code: BiometryErrorType.none,
|
|
15
16
|
});
|
|
16
17
|
}
|
|
17
18
|
async authenticate(options) {
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var core = require('@capacitor/core');
|
|
6
4
|
var app = require('@capacitor/app');
|
|
7
5
|
|
|
8
|
-
var info = {
|
|
9
|
-
name: "@aparajita/capacitor-biometric-auth",
|
|
10
|
-
version: "3.1.4"
|
|
11
|
-
};
|
|
12
|
-
|
|
13
6
|
exports.BiometryType = void 0;
|
|
14
7
|
(function (BiometryType) {
|
|
15
8
|
/**
|
|
@@ -47,23 +40,24 @@ exports.BiometryType = void 0;
|
|
|
47
40
|
*/
|
|
48
41
|
exports.BiometryErrorType = void 0;
|
|
49
42
|
(function (BiometryErrorType) {
|
|
50
|
-
BiometryErrorType[
|
|
51
|
-
BiometryErrorType[
|
|
52
|
-
BiometryErrorType[
|
|
53
|
-
BiometryErrorType[
|
|
54
|
-
BiometryErrorType[
|
|
55
|
-
BiometryErrorType[
|
|
56
|
-
BiometryErrorType[
|
|
57
|
-
BiometryErrorType[
|
|
58
|
-
BiometryErrorType[
|
|
59
|
-
BiometryErrorType[
|
|
60
|
-
BiometryErrorType[
|
|
61
|
-
BiometryErrorType[
|
|
43
|
+
BiometryErrorType["none"] = "";
|
|
44
|
+
BiometryErrorType["appCancel"] = "appCancel";
|
|
45
|
+
BiometryErrorType["authenticationFailed"] = "authenticationFailed";
|
|
46
|
+
BiometryErrorType["invalidContext"] = "invalidContext";
|
|
47
|
+
BiometryErrorType["notInteractive"] = "notInteractive";
|
|
48
|
+
BiometryErrorType["passcodeNotSet"] = "passcodeNotSet";
|
|
49
|
+
BiometryErrorType["systemCancel"] = "systemCancel";
|
|
50
|
+
BiometryErrorType["userCancel"] = "userCancel";
|
|
51
|
+
BiometryErrorType["userFallback"] = "userFallback";
|
|
52
|
+
BiometryErrorType["biometryLockout"] = "biometryLockout";
|
|
53
|
+
BiometryErrorType["biometryNotAvailable"] = "biometryNotAvailable";
|
|
54
|
+
BiometryErrorType["biometryNotEnrolled"] = "biometryNotEnrolled";
|
|
55
|
+
BiometryErrorType["noDeviceCredential"] = "noDeviceCredential";
|
|
62
56
|
})(exports.BiometryErrorType || (exports.BiometryErrorType = {}));
|
|
63
57
|
class BiometryError {
|
|
64
58
|
constructor(message, code) {
|
|
65
59
|
this.message = message;
|
|
66
|
-
this.code =
|
|
60
|
+
this.code = code;
|
|
67
61
|
}
|
|
68
62
|
}
|
|
69
63
|
|
|
@@ -73,7 +67,7 @@ const kBiometryTypeNameMap = {
|
|
|
73
67
|
[exports.BiometryType.faceId]: 'Face ID',
|
|
74
68
|
[exports.BiometryType.fingerprintAuthentication]: 'Fingerprint Authentication',
|
|
75
69
|
[exports.BiometryType.faceAuthentication]: 'Face Authentication',
|
|
76
|
-
[exports.BiometryType.irisAuthentication]: 'Iris Authentication'
|
|
70
|
+
[exports.BiometryType.irisAuthentication]: 'Iris Authentication',
|
|
77
71
|
};
|
|
78
72
|
/**
|
|
79
73
|
* Return a human-readable name for a BiometryType.
|
|
@@ -83,11 +77,10 @@ function getBiometryName(type) {
|
|
|
83
77
|
return kBiometryTypeNameMap[type] || '';
|
|
84
78
|
}
|
|
85
79
|
|
|
86
|
-
console.log(`loaded ${info.name} v${info.version}`);
|
|
87
80
|
const proxy = core.registerPlugin('BiometricAuthNative', {
|
|
88
81
|
web: async () => Promise.resolve().then(function () { return web; }).then((module) => new module.BiometricAuthWeb()),
|
|
89
82
|
ios: async () => Promise.resolve().then(function () { return native; }).then((module) => new module.BiometricAuthNative(proxy)),
|
|
90
|
-
android: async () => Promise.resolve().then(function () { return native; }).then((module) => new module.BiometricAuthNative(proxy))
|
|
83
|
+
android: async () => Promise.resolve().then(function () { return native; }).then((module) => new module.BiometricAuthNative(proxy)),
|
|
91
84
|
});
|
|
92
85
|
|
|
93
86
|
// eslint-disable-next-line import/prefer-default-export
|
|
@@ -115,7 +108,8 @@ class BiometricAuthWeb extends BiometricAuthBase {
|
|
|
115
108
|
return Promise.resolve({
|
|
116
109
|
isAvailable: this.biometryType !== exports.BiometryType.none,
|
|
117
110
|
biometryType: this.biometryType,
|
|
118
|
-
reason: ''
|
|
111
|
+
reason: '',
|
|
112
|
+
code: exports.BiometryErrorType.none,
|
|
119
113
|
});
|
|
120
114
|
}
|
|
121
115
|
async authenticate(options) {
|
|
@@ -167,7 +161,8 @@ class BiometricAuthNative extends BiometricAuthBase {
|
|
|
167
161
|
return Promise.resolve({
|
|
168
162
|
isAvailable: true,
|
|
169
163
|
biometryType: exports.BiometryType.none,
|
|
170
|
-
reason: ''
|
|
164
|
+
reason: '',
|
|
165
|
+
code: exports.BiometryErrorType.none,
|
|
171
166
|
});
|
|
172
167
|
}
|
|
173
168
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
|
package/dist/plugin.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
var capacitorBiometricAuth = (function (exports, core, app) {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var info = {
|
|
5
|
-
name: "@aparajita/capacitor-biometric-auth",
|
|
6
|
-
version: "3.1.4"
|
|
7
|
-
};
|
|
8
|
-
|
|
9
4
|
exports.BiometryType = void 0;
|
|
10
5
|
(function (BiometryType) {
|
|
11
6
|
/**
|
|
@@ -43,23 +38,24 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
43
38
|
*/
|
|
44
39
|
exports.BiometryErrorType = void 0;
|
|
45
40
|
(function (BiometryErrorType) {
|
|
46
|
-
BiometryErrorType[
|
|
47
|
-
BiometryErrorType[
|
|
48
|
-
BiometryErrorType[
|
|
49
|
-
BiometryErrorType[
|
|
50
|
-
BiometryErrorType[
|
|
51
|
-
BiometryErrorType[
|
|
52
|
-
BiometryErrorType[
|
|
53
|
-
BiometryErrorType[
|
|
54
|
-
BiometryErrorType[
|
|
55
|
-
BiometryErrorType[
|
|
56
|
-
BiometryErrorType[
|
|
57
|
-
BiometryErrorType[
|
|
41
|
+
BiometryErrorType["none"] = "";
|
|
42
|
+
BiometryErrorType["appCancel"] = "appCancel";
|
|
43
|
+
BiometryErrorType["authenticationFailed"] = "authenticationFailed";
|
|
44
|
+
BiometryErrorType["invalidContext"] = "invalidContext";
|
|
45
|
+
BiometryErrorType["notInteractive"] = "notInteractive";
|
|
46
|
+
BiometryErrorType["passcodeNotSet"] = "passcodeNotSet";
|
|
47
|
+
BiometryErrorType["systemCancel"] = "systemCancel";
|
|
48
|
+
BiometryErrorType["userCancel"] = "userCancel";
|
|
49
|
+
BiometryErrorType["userFallback"] = "userFallback";
|
|
50
|
+
BiometryErrorType["biometryLockout"] = "biometryLockout";
|
|
51
|
+
BiometryErrorType["biometryNotAvailable"] = "biometryNotAvailable";
|
|
52
|
+
BiometryErrorType["biometryNotEnrolled"] = "biometryNotEnrolled";
|
|
53
|
+
BiometryErrorType["noDeviceCredential"] = "noDeviceCredential";
|
|
58
54
|
})(exports.BiometryErrorType || (exports.BiometryErrorType = {}));
|
|
59
55
|
class BiometryError {
|
|
60
56
|
constructor(message, code) {
|
|
61
57
|
this.message = message;
|
|
62
|
-
this.code =
|
|
58
|
+
this.code = code;
|
|
63
59
|
}
|
|
64
60
|
}
|
|
65
61
|
|
|
@@ -69,7 +65,7 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
69
65
|
[exports.BiometryType.faceId]: 'Face ID',
|
|
70
66
|
[exports.BiometryType.fingerprintAuthentication]: 'Fingerprint Authentication',
|
|
71
67
|
[exports.BiometryType.faceAuthentication]: 'Face Authentication',
|
|
72
|
-
[exports.BiometryType.irisAuthentication]: 'Iris Authentication'
|
|
68
|
+
[exports.BiometryType.irisAuthentication]: 'Iris Authentication',
|
|
73
69
|
};
|
|
74
70
|
/**
|
|
75
71
|
* Return a human-readable name for a BiometryType.
|
|
@@ -79,11 +75,10 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
79
75
|
return kBiometryTypeNameMap[type] || '';
|
|
80
76
|
}
|
|
81
77
|
|
|
82
|
-
console.log(`loaded ${info.name} v${info.version}`);
|
|
83
78
|
const proxy = core.registerPlugin('BiometricAuthNative', {
|
|
84
79
|
web: async () => Promise.resolve().then(function () { return web; }).then((module) => new module.BiometricAuthWeb()),
|
|
85
80
|
ios: async () => Promise.resolve().then(function () { return native; }).then((module) => new module.BiometricAuthNative(proxy)),
|
|
86
|
-
android: async () => Promise.resolve().then(function () { return native; }).then((module) => new module.BiometricAuthNative(proxy))
|
|
81
|
+
android: async () => Promise.resolve().then(function () { return native; }).then((module) => new module.BiometricAuthNative(proxy)),
|
|
87
82
|
});
|
|
88
83
|
|
|
89
84
|
// eslint-disable-next-line import/prefer-default-export
|
|
@@ -111,7 +106,8 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
111
106
|
return Promise.resolve({
|
|
112
107
|
isAvailable: this.biometryType !== exports.BiometryType.none,
|
|
113
108
|
biometryType: this.biometryType,
|
|
114
|
-
reason: ''
|
|
109
|
+
reason: '',
|
|
110
|
+
code: exports.BiometryErrorType.none,
|
|
115
111
|
});
|
|
116
112
|
}
|
|
117
113
|
async authenticate(options) {
|
|
@@ -163,7 +159,8 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
163
159
|
return Promise.resolve({
|
|
164
160
|
isAvailable: true,
|
|
165
161
|
biometryType: exports.BiometryType.none,
|
|
166
|
-
reason: ''
|
|
162
|
+
reason: '',
|
|
163
|
+
code: exports.BiometryErrorType.none,
|
|
167
164
|
});
|
|
168
165
|
}
|
|
169
166
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
|
|
@@ -185,8 +182,6 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
185
182
|
exports.BiometryError = BiometryError;
|
|
186
183
|
exports.getBiometryName = getBiometryName;
|
|
187
184
|
|
|
188
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
189
|
-
|
|
190
185
|
return exports;
|
|
191
186
|
|
|
192
187
|
})({}, capacitorExports, app);
|
package/ios/Plugin/Plugin.m
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
#import <Foundation/Foundation.h>
|
|
2
2
|
#import <Capacitor/Capacitor.h>
|
|
3
3
|
|
|
4
|
-
// Generated by @aparajita/capacitor-native-decorator/make-ios-plugin
|
|
5
|
-
|
|
6
4
|
CAP_PLUGIN(BiometricAuthNative, "BiometricAuthNative",
|
|
7
5
|
CAP_PLUGIN_METHOD(checkBiometry, CAPPluginReturnPromise);
|
|
8
6
|
CAP_PLUGIN_METHOD(authenticate, CAPPluginReturnPromise);
|
package/ios/Plugin/Plugin.swift
CHANGED
|
@@ -7,18 +7,18 @@ private let kMissingFaceIDUsageEntry = "The device supports Face ID, but NSFaceI
|
|
|
7
7
|
|
|
8
8
|
@objc(BiometricAuthNative)
|
|
9
9
|
public class BiometricAuthNative: CAPPlugin {
|
|
10
|
-
let biometryErrorCodeMap: [
|
|
11
|
-
.appCancel: "appCancel",
|
|
12
|
-
.authenticationFailed: "authenticationFailed",
|
|
13
|
-
.invalidContext: "invalidContext",
|
|
14
|
-
.notInteractive: "notInteractive",
|
|
15
|
-
.passcodeNotSet: "passcodeNotSet",
|
|
16
|
-
.systemCancel: "systemCancel",
|
|
17
|
-
.userCancel: "userCancel",
|
|
18
|
-
.userFallback: "userFallback",
|
|
19
|
-
.biometryLockout: "biometryLockout",
|
|
20
|
-
.biometryNotAvailable: "biometryNotAvailable",
|
|
21
|
-
.biometryNotEnrolled: "biometryNotEnrolled"
|
|
10
|
+
let biometryErrorCodeMap: [Int: String] = [
|
|
11
|
+
LAError.appCancel.rawValue: "appCancel",
|
|
12
|
+
LAError.authenticationFailed.rawValue: "authenticationFailed",
|
|
13
|
+
LAError.invalidContext.rawValue: "invalidContext",
|
|
14
|
+
LAError.notInteractive.rawValue: "notInteractive",
|
|
15
|
+
LAError.passcodeNotSet.rawValue: "passcodeNotSet",
|
|
16
|
+
LAError.systemCancel.rawValue: "systemCancel",
|
|
17
|
+
LAError.userCancel.rawValue: "userCancel",
|
|
18
|
+
LAError.userFallback.rawValue: "userFallback",
|
|
19
|
+
LAError.biometryLockout.rawValue: "biometryLockout",
|
|
20
|
+
LAError.biometryNotAvailable.rawValue: "biometryNotAvailable",
|
|
21
|
+
LAError.biometryNotEnrolled.rawValue: "biometryNotEnrolled",
|
|
22
22
|
]
|
|
23
23
|
|
|
24
24
|
var canEvaluatePolicy = true
|
|
@@ -31,6 +31,7 @@ public class BiometricAuthNative: CAPPlugin {
|
|
|
31
31
|
var error: NSError?
|
|
32
32
|
var available = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
|
|
33
33
|
var reason = ""
|
|
34
|
+
var errorCode = ""
|
|
34
35
|
|
|
35
36
|
if available, context.biometryType == .faceID {
|
|
36
37
|
// The system may report that biometry is available, but if the type is Face ID
|
|
@@ -42,6 +43,7 @@ public class BiometricAuthNative: CAPPlugin {
|
|
|
42
43
|
available = false
|
|
43
44
|
canEvaluatePolicy = false
|
|
44
45
|
reason = kMissingFaceIDUsageEntry
|
|
46
|
+
errorCode = biometryErrorCodeMap[LAError.biometryNotAvailable.rawValue] ?? ""
|
|
45
47
|
}
|
|
46
48
|
} else if !available,
|
|
47
49
|
let error = error {
|
|
@@ -51,12 +53,15 @@ public class BiometricAuthNative: CAPPlugin {
|
|
|
51
53
|
if let failureReason = error.localizedFailureReason {
|
|
52
54
|
reason = "\(reason): \(failureReason)"
|
|
53
55
|
}
|
|
56
|
+
|
|
57
|
+
errorCode = biometryErrorCodeMap[error.code] ?? biometryErrorCodeMap[LAError.biometryNotAvailable.rawValue] ?? ""
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
call.resolve([
|
|
57
61
|
"isAvailable": available,
|
|
58
62
|
"biometryType": context.biometryType.rawValue,
|
|
59
|
-
"reason": reason
|
|
63
|
+
"reason": reason,
|
|
64
|
+
"code": errorCode
|
|
60
65
|
])
|
|
61
66
|
}
|
|
62
67
|
|
|
@@ -72,7 +77,7 @@ public class BiometricAuthNative: CAPPlugin {
|
|
|
72
77
|
guard canEvaluatePolicy else {
|
|
73
78
|
call.reject(
|
|
74
79
|
kMissingFaceIDUsageEntry,
|
|
75
|
-
biometryErrorCodeMap[.biometryNotAvailable]
|
|
80
|
+
biometryErrorCodeMap[LAError.biometryNotAvailable.rawValue]
|
|
76
81
|
)
|
|
77
82
|
|
|
78
83
|
return
|
|
@@ -111,10 +116,10 @@ public class BiometricAuthNative: CAPPlugin {
|
|
|
111
116
|
call.resolve()
|
|
112
117
|
} else {
|
|
113
118
|
if let policyError = error as? LAError {
|
|
114
|
-
let code = self.biometryErrorCodeMap[policyError.code]
|
|
119
|
+
let code = self.biometryErrorCodeMap[policyError.code.rawValue]
|
|
115
120
|
call.reject(policyError.localizedDescription, code)
|
|
116
121
|
} else {
|
|
117
|
-
call.reject("An unknown error occurred.", self.biometryErrorCodeMap[.authenticationFailed])
|
|
122
|
+
call.reject("An unknown error occurred.", self.biometryErrorCodeMap[LAError.authenticationFailed.rawValue])
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
125
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aparajita/capacitor-biometric-auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Provides access to the native biometric auth APIs for Capacitor apps",
|
|
5
5
|
"author": "Aparajita Fishman",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,46 +56,44 @@
|
|
|
56
56
|
"@aparajita/eslint-config-base": "^1.1.5",
|
|
57
57
|
"@aparajita/prettier-config": "^1.0.0",
|
|
58
58
|
"@aparajita/swiftly": "^1.0.4",
|
|
59
|
-
"@capacitor/cli": "^
|
|
60
|
-
"@commitlint/cli": "^17.
|
|
61
|
-
"@commitlint/config-conventional": "^17.
|
|
59
|
+
"@capacitor/cli": "^5.0.5",
|
|
60
|
+
"@commitlint/cli": "^17.6.5",
|
|
61
|
+
"@commitlint/config-conventional": "^17.6.5",
|
|
62
62
|
"@ionic/swiftlint-config": "^1.1.2",
|
|
63
|
-
"@rollup/plugin-json": "^
|
|
64
|
-
"@types/node": "^
|
|
65
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
66
|
-
"@typescript-eslint/parser": "^5.
|
|
67
|
-
"commit-and-tag-version": "^
|
|
68
|
-
"eslint": "^8.
|
|
69
|
-
"eslint-config-prettier": "^8.
|
|
70
|
-
"eslint-config-standard": "^17.
|
|
71
|
-
"eslint-import-resolver-typescript": "^3.
|
|
72
|
-
"eslint-plugin-import": "^2.
|
|
73
|
-
"eslint-plugin-n": "^
|
|
63
|
+
"@rollup/plugin-json": "^6.0.0",
|
|
64
|
+
"@types/node": "^20.3.1",
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^5.59.11",
|
|
66
|
+
"@typescript-eslint/parser": "^5.59.11",
|
|
67
|
+
"commit-and-tag-version": "^11.2.1",
|
|
68
|
+
"eslint": "^8.42.0",
|
|
69
|
+
"eslint-config-prettier": "^8.8.0",
|
|
70
|
+
"eslint-config-standard": "^17.1.0",
|
|
71
|
+
"eslint-import-resolver-typescript": "^3.5.5",
|
|
72
|
+
"eslint-plugin-import": "^2.27.5",
|
|
73
|
+
"eslint-plugin-n": "^16.0.0",
|
|
74
74
|
"eslint-plugin-prettier": "^4.2.1",
|
|
75
|
-
"eslint-plugin-promise": "^6.
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"prettier": "^2.
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"typescript": "~4.7.4"
|
|
75
|
+
"eslint-plugin-promise": "^6.1.1",
|
|
76
|
+
"nodemon": "^2.0.22",
|
|
77
|
+
"prettier": "^2.8.8",
|
|
78
|
+
"prettier-plugin-java": "^2.1.0",
|
|
79
|
+
"rimraf": "^5.0.1",
|
|
80
|
+
"rollup": "^3.25.1",
|
|
81
|
+
"swiftlint": "^1.0.2",
|
|
82
|
+
"typescript": "~5.1.3"
|
|
84
83
|
},
|
|
85
84
|
"dependencies": {
|
|
86
|
-
"@capacitor/android": "^
|
|
87
|
-
"@capacitor/app": "^
|
|
88
|
-
"@capacitor/core": "^
|
|
89
|
-
"@capacitor/ios": "^
|
|
85
|
+
"@capacitor/android": "^5.0.5",
|
|
86
|
+
"@capacitor/app": "^5.0.3",
|
|
87
|
+
"@capacitor/core": "^5.0.5",
|
|
88
|
+
"@capacitor/ios": "^5.0.5"
|
|
90
89
|
},
|
|
91
90
|
"scripts": {
|
|
92
91
|
"clean": "rimraf dist",
|
|
93
|
-
"extract-info": "node scripts/extractPackageInfo.js",
|
|
94
92
|
"lint.eslint": "eslint --fix --cache --ext .js,.cjs,.mjs,.ts --max-warnings 0",
|
|
95
93
|
"lint.prettier": "prettier --write --cache --list-different",
|
|
96
94
|
"lint.tsc": "tsc --noEmit",
|
|
97
95
|
"lint": "pnpm lint.eslint . && pnpm lint.prettier . && pnpm lint.tsc",
|
|
98
|
-
"prebuilder": "pnpm clean
|
|
96
|
+
"prebuilder": "pnpm clean",
|
|
99
97
|
"builder": "tsc ${SOURCE_MAP:-} && rollup -c rollup.config.mjs",
|
|
100
98
|
"prebuild": "pnpm lint",
|
|
101
99
|
"build": "pnpm builder",
|
package/dist/esm/info.json
DELETED