@aparajita/capacitor-biometric-auth 3.1.3 → 4.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 CHANGED
@@ -28,6 +28,8 @@ Not using [pnpm](https://pnpm.js.org/)? You owe it to yourself to give it a try.
28
28
 
29
29
  The API is extensively documented in the [TypeScript definitions file](src/definitions.ts). There is also (somewhat incomplete auto-generated) documentation [below](#api). For a complete example of how to use this plugin in practice, see the [demo app](https://github.com/aparajita/capacitor-biometric-auth-demo).
30
30
 
31
+ > **NOTE:** Your Android app must use a base theme named "AppTheme".
32
+
31
33
  ### Checking availability
32
34
 
33
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.
@@ -107,7 +109,7 @@ web only<br><br>On the web, this method allows you to dynamically simulate diffe
107
109
  authenticate(options?: AuthenticateOptions) => Promise<void>
108
110
  ```
109
111
 
110
- 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>Android imposes a limit of 5 failed attempts. If `allowDeviceCredential` is `true`, the user will then be presented with a device credential prompt. If `allowDeviceCredential` is `false`, `authenticate()` will reject with a `BiometryErrorType` of `biometryLockout`, after which the user will have to wait 30 seconds before being allowed to authenticate again.
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.
111
113
 
112
114
  | Param | Type |
113
115
  | :------ | :----------------------------------------------------- |
@@ -135,11 +137,12 @@ Register a function that will be called when the app resumes. The function will
135
137
 
136
138
  #### CheckBiometryResult
137
139
 
138
- | Prop | Type | Description |
139
- | :----------- | :--------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ |
140
- | isAvailable | boolean | True if the device has biometric authentication capability and the current user has enrolled in biometry. |
141
- | biometryType | <a href="#biometrytype">BiometryType</a> | The type of biometry available on the device. |
142
- | 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. |
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>) { ... } |
143
146
 
144
147
  #### AuthenticateOptions
145
148
 
@@ -179,5 +182,23 @@ The signature of the callback passed to `addResumeListener()`.
179
182
  | faceAuthentication | Android face authentication is available |
180
183
  | irisAuthentication | Android iris authentication is available |
181
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
+
182
203
  </docgen-api>
183
204
  </div>
@@ -5,7 +5,7 @@
5
5
  <application>
6
6
  <activity
7
7
  android:name=".AuthActivity"
8
- android:label="@string/title_activity_auth_acitivy"
8
+ android:label="@string/title_activity_auth_activity"
9
9
  android:theme="@style/AppTheme.Transparent"/>
10
10
  </application>
11
11
 
@@ -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't authenticate because a security vulnerability has been discovered with one or more hardware sensors.";
123
+ reason = "The user cant 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't authenticate because the specified options are incompatible with the current Android version.";
126
+ reason = "The user cant 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
 
@@ -1,12 +1,3 @@
1
1
  <resources>
2
- <string name="my_string">Just a simple string</string>
3
- <string name="title_activity_auth_acitivy">AuthAcitivy</string>
4
- <!-- Strings used for fragments for navigation -->
5
- <string name="first_fragment_label">First Fragment</string>
6
- <string name="second_fragment_label">Second Fragment</string>
7
- <string name="next">Next</string>
8
- <string name="previous">Previous</string>
9
-
10
- <string name="hello_first_fragment">Hello first fragment</string>
11
- <string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
2
+ <string name="title_activity_auth_activity">AuthActivity</string>
12
3
  </resources>
@@ -1,11 +1,5 @@
1
1
  <resources>
2
2
 
3
-
4
- <style name="AppTheme.NoActionBar">
5
- <item name="windowActionBar">false</item>
6
- <item name="windowNoTitle">true</item>
7
- </style>
8
-
9
3
  <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
10
4
 
11
5
  <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
@@ -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
- appCancel = 0,
114
- authenticationFailed = 1,
115
- invalidContext = 2,
116
- notInteractive = 3,
117
- passcodeNotSet = 4,
118
- systemCancel = 5,
119
- userCancel = 6,
120
- userFallback = 7,
121
- biometryLockout = 8,
122
- biometryNotAvailable = 9,
123
- biometryNotEnrolled = 10,
124
- noDeviceCredential = 11
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,6 +147,18 @@ 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()`.
@@ -173,11 +186,13 @@ export interface BiometricAuthPlugin extends WebPlugin {
173
186
  *
174
187
  * https://developer.apple.com/documentation/localauthentication/lapolicy/deviceownerauthenticationwithbiometrics
175
188
  *
176
- * Android imposes a limit of 5 failed attempts. If `allowDeviceCredential` is
177
- * `true`, the user will then be presented with a device credential prompt.
178
- * If `allowDeviceCredential` is `false`, `authenticate()` will reject with
179
- * a `BiometryErrorType` of `biometryLockout`, after which the user will have
180
- * to wait 30 seconds before being allowed to authenticate again.
189
+ * Some versions of Android impose a limit on the number of failed attempts.
190
+ * If `allowDeviceCredential` is `true`, when the limit is reached
191
+ * the user will then be presented with a device credential prompt.
192
+ * If `allowDeviceCredential` is `false`, when the limit is reached
193
+ * `authenticate()` will reject with a `BiometryErrorType` of `biometryLockout`,
194
+ * after which the user will have to wait the system-defined length of time
195
+ * before being allowed to authenticate again.
181
196
  *
182
197
  * @rejects {BiometryError}
183
198
  */
@@ -35,22 +35,23 @@ export var BiometryType;
35
35
  */
36
36
  export var BiometryErrorType;
37
37
  (function (BiometryErrorType) {
38
- BiometryErrorType[BiometryErrorType["appCancel"] = 0] = "appCancel";
39
- BiometryErrorType[BiometryErrorType["authenticationFailed"] = 1] = "authenticationFailed";
40
- BiometryErrorType[BiometryErrorType["invalidContext"] = 2] = "invalidContext";
41
- BiometryErrorType[BiometryErrorType["notInteractive"] = 3] = "notInteractive";
42
- BiometryErrorType[BiometryErrorType["passcodeNotSet"] = 4] = "passcodeNotSet";
43
- BiometryErrorType[BiometryErrorType["systemCancel"] = 5] = "systemCancel";
44
- BiometryErrorType[BiometryErrorType["userCancel"] = 6] = "userCancel";
45
- BiometryErrorType[BiometryErrorType["userFallback"] = 7] = "userFallback";
46
- BiometryErrorType[BiometryErrorType["biometryLockout"] = 8] = "biometryLockout";
47
- BiometryErrorType[BiometryErrorType["biometryNotAvailable"] = 9] = "biometryNotAvailable";
48
- BiometryErrorType[BiometryErrorType["biometryNotEnrolled"] = 10] = "biometryNotEnrolled";
49
- BiometryErrorType[BiometryErrorType["noDeviceCredential"] = 11] = "noDeviceCredential";
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 = BiometryErrorType[code];
55
+ this.code = code;
55
56
  }
56
57
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "@aparajita/capacitor-biometric-auth",
3
- "version": "3.1.3"
3
+ "version": "4.0.0"
4
4
  }
@@ -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.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) {
@@ -1,13 +1,11 @@
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
6
  var info = {
9
7
  name: "@aparajita/capacitor-biometric-auth",
10
- version: "3.1.3"
8
+ version: "4.0.0"
11
9
  };
12
10
 
13
11
  exports.BiometryType = void 0;
@@ -47,23 +45,24 @@ exports.BiometryType = void 0;
47
45
  */
48
46
  exports.BiometryErrorType = void 0;
49
47
  (function (BiometryErrorType) {
50
- BiometryErrorType[BiometryErrorType["appCancel"] = 0] = "appCancel";
51
- BiometryErrorType[BiometryErrorType["authenticationFailed"] = 1] = "authenticationFailed";
52
- BiometryErrorType[BiometryErrorType["invalidContext"] = 2] = "invalidContext";
53
- BiometryErrorType[BiometryErrorType["notInteractive"] = 3] = "notInteractive";
54
- BiometryErrorType[BiometryErrorType["passcodeNotSet"] = 4] = "passcodeNotSet";
55
- BiometryErrorType[BiometryErrorType["systemCancel"] = 5] = "systemCancel";
56
- BiometryErrorType[BiometryErrorType["userCancel"] = 6] = "userCancel";
57
- BiometryErrorType[BiometryErrorType["userFallback"] = 7] = "userFallback";
58
- BiometryErrorType[BiometryErrorType["biometryLockout"] = 8] = "biometryLockout";
59
- BiometryErrorType[BiometryErrorType["biometryNotAvailable"] = 9] = "biometryNotAvailable";
60
- BiometryErrorType[BiometryErrorType["biometryNotEnrolled"] = 10] = "biometryNotEnrolled";
61
- BiometryErrorType[BiometryErrorType["noDeviceCredential"] = 11] = "noDeviceCredential";
48
+ BiometryErrorType["none"] = "";
49
+ BiometryErrorType["appCancel"] = "appCancel";
50
+ BiometryErrorType["authenticationFailed"] = "authenticationFailed";
51
+ BiometryErrorType["invalidContext"] = "invalidContext";
52
+ BiometryErrorType["notInteractive"] = "notInteractive";
53
+ BiometryErrorType["passcodeNotSet"] = "passcodeNotSet";
54
+ BiometryErrorType["systemCancel"] = "systemCancel";
55
+ BiometryErrorType["userCancel"] = "userCancel";
56
+ BiometryErrorType["userFallback"] = "userFallback";
57
+ BiometryErrorType["biometryLockout"] = "biometryLockout";
58
+ BiometryErrorType["biometryNotAvailable"] = "biometryNotAvailable";
59
+ BiometryErrorType["biometryNotEnrolled"] = "biometryNotEnrolled";
60
+ BiometryErrorType["noDeviceCredential"] = "noDeviceCredential";
62
61
  })(exports.BiometryErrorType || (exports.BiometryErrorType = {}));
63
62
  class BiometryError {
64
63
  constructor(message, code) {
65
64
  this.message = message;
66
- this.code = exports.BiometryErrorType[code];
65
+ this.code = code;
67
66
  }
68
67
  }
69
68
 
@@ -115,7 +114,8 @@ class BiometricAuthWeb extends BiometricAuthBase {
115
114
  return Promise.resolve({
116
115
  isAvailable: this.biometryType !== exports.BiometryType.none,
117
116
  biometryType: this.biometryType,
118
- reason: ''
117
+ reason: '',
118
+ code: exports.BiometryErrorType.none
119
119
  });
120
120
  }
121
121
  async authenticate(options) {
@@ -167,7 +167,8 @@ class BiometricAuthNative extends BiometricAuthBase {
167
167
  return Promise.resolve({
168
168
  isAvailable: true,
169
169
  biometryType: exports.BiometryType.none,
170
- reason: ''
170
+ reason: '',
171
+ code: exports.BiometryErrorType.none
171
172
  });
172
173
  }
173
174
  // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
package/dist/plugin.js CHANGED
@@ -3,7 +3,7 @@ var capacitorBiometricAuth = (function (exports, core, app) {
3
3
 
4
4
  var info = {
5
5
  name: "@aparajita/capacitor-biometric-auth",
6
- version: "3.1.3"
6
+ version: "4.0.0"
7
7
  };
8
8
 
9
9
  exports.BiometryType = void 0;
@@ -43,23 +43,24 @@ var capacitorBiometricAuth = (function (exports, core, app) {
43
43
  */
44
44
  exports.BiometryErrorType = void 0;
45
45
  (function (BiometryErrorType) {
46
- BiometryErrorType[BiometryErrorType["appCancel"] = 0] = "appCancel";
47
- BiometryErrorType[BiometryErrorType["authenticationFailed"] = 1] = "authenticationFailed";
48
- BiometryErrorType[BiometryErrorType["invalidContext"] = 2] = "invalidContext";
49
- BiometryErrorType[BiometryErrorType["notInteractive"] = 3] = "notInteractive";
50
- BiometryErrorType[BiometryErrorType["passcodeNotSet"] = 4] = "passcodeNotSet";
51
- BiometryErrorType[BiometryErrorType["systemCancel"] = 5] = "systemCancel";
52
- BiometryErrorType[BiometryErrorType["userCancel"] = 6] = "userCancel";
53
- BiometryErrorType[BiometryErrorType["userFallback"] = 7] = "userFallback";
54
- BiometryErrorType[BiometryErrorType["biometryLockout"] = 8] = "biometryLockout";
55
- BiometryErrorType[BiometryErrorType["biometryNotAvailable"] = 9] = "biometryNotAvailable";
56
- BiometryErrorType[BiometryErrorType["biometryNotEnrolled"] = 10] = "biometryNotEnrolled";
57
- BiometryErrorType[BiometryErrorType["noDeviceCredential"] = 11] = "noDeviceCredential";
46
+ BiometryErrorType["none"] = "";
47
+ BiometryErrorType["appCancel"] = "appCancel";
48
+ BiometryErrorType["authenticationFailed"] = "authenticationFailed";
49
+ BiometryErrorType["invalidContext"] = "invalidContext";
50
+ BiometryErrorType["notInteractive"] = "notInteractive";
51
+ BiometryErrorType["passcodeNotSet"] = "passcodeNotSet";
52
+ BiometryErrorType["systemCancel"] = "systemCancel";
53
+ BiometryErrorType["userCancel"] = "userCancel";
54
+ BiometryErrorType["userFallback"] = "userFallback";
55
+ BiometryErrorType["biometryLockout"] = "biometryLockout";
56
+ BiometryErrorType["biometryNotAvailable"] = "biometryNotAvailable";
57
+ BiometryErrorType["biometryNotEnrolled"] = "biometryNotEnrolled";
58
+ BiometryErrorType["noDeviceCredential"] = "noDeviceCredential";
58
59
  })(exports.BiometryErrorType || (exports.BiometryErrorType = {}));
59
60
  class BiometryError {
60
61
  constructor(message, code) {
61
62
  this.message = message;
62
- this.code = exports.BiometryErrorType[code];
63
+ this.code = code;
63
64
  }
64
65
  }
65
66
 
@@ -111,7 +112,8 @@ var capacitorBiometricAuth = (function (exports, core, app) {
111
112
  return Promise.resolve({
112
113
  isAvailable: this.biometryType !== exports.BiometryType.none,
113
114
  biometryType: this.biometryType,
114
- reason: ''
115
+ reason: '',
116
+ code: exports.BiometryErrorType.none
115
117
  });
116
118
  }
117
119
  async authenticate(options) {
@@ -163,7 +165,8 @@ var capacitorBiometricAuth = (function (exports, core, app) {
163
165
  return Promise.resolve({
164
166
  isAvailable: true,
165
167
  biometryType: exports.BiometryType.none,
166
- reason: ''
168
+ reason: '',
169
+ code: exports.BiometryErrorType.none
167
170
  });
168
171
  }
169
172
  // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function
@@ -185,8 +188,6 @@ var capacitorBiometricAuth = (function (exports, core, app) {
185
188
  exports.BiometryError = BiometryError;
186
189
  exports.getBiometryName = getBiometryName;
187
190
 
188
- Object.defineProperty(exports, '__esModule', { value: true });
189
-
190
191
  return exports;
191
192
 
192
193
  })({}, capacitorExports, app);
@@ -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: [LAError.Code: String] = [
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.1.3",
3
+ "version": "4.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,37 +56,37 @@
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": "^4.0.1",
60
- "@commitlint/cli": "^17.0.3",
61
- "@commitlint/config-conventional": "^17.0.3",
59
+ "@capacitor/cli": "^4.7.2",
60
+ "@commitlint/cli": "^17.5.1",
61
+ "@commitlint/config-conventional": "^17.4.4",
62
62
  "@ionic/swiftlint-config": "^1.1.2",
63
- "@rollup/plugin-json": "^4.1.0",
64
- "@types/node": "^18.6.5",
65
- "@typescript-eslint/eslint-plugin": "^5.33.0",
66
- "@typescript-eslint/parser": "^5.33.0",
67
- "commit-and-tag-version": "^10.0.1",
68
- "eslint": "^8.21.0",
69
- "eslint-config-prettier": "^8.5.0",
63
+ "@rollup/plugin-json": "^6.0.0",
64
+ "@types/node": "^18.15.11",
65
+ "@typescript-eslint/eslint-plugin": "^5.57.0",
66
+ "@typescript-eslint/parser": "^5.57.0",
67
+ "commit-and-tag-version": "^11.2.0",
68
+ "eslint": "^8.37.0",
69
+ "eslint-config-prettier": "^8.8.0",
70
70
  "eslint-config-standard": "^17.0.0",
71
- "eslint-import-resolver-typescript": "^3.4.0",
72
- "eslint-plugin-import": "^2.26.0",
73
- "eslint-plugin-n": "^15.2.4",
71
+ "eslint-import-resolver-typescript": "^3.5.4",
72
+ "eslint-plugin-import": "^2.27.5",
73
+ "eslint-plugin-n": "^15.7.0",
74
74
  "eslint-plugin-prettier": "^4.2.1",
75
- "eslint-plugin-promise": "^6.0.0",
76
- "husky": "^8.0.1",
77
- "nodemon": "^2.0.19",
78
- "prettier": "^2.7.1",
79
- "prettier-plugin-java": "^1.6.2",
80
- "rimraf": "^3.0.2",
81
- "rollup": "^2.77.2",
75
+ "eslint-plugin-promise": "^6.1.1",
76
+ "husky": "^8.0.3",
77
+ "nodemon": "^2.0.22",
78
+ "prettier": "^2.8.7",
79
+ "prettier-plugin-java": "^2.1.0",
80
+ "rimraf": "^4.4.1",
81
+ "rollup": "^3.20.2",
82
82
  "swiftlint": "^1.0.1",
83
83
  "typescript": "~4.7.4"
84
84
  },
85
85
  "dependencies": {
86
- "@capacitor/android": "^4.0.1",
87
- "@capacitor/app": "^4.0.1",
88
- "@capacitor/core": "^4.0.1",
89
- "@capacitor/ios": "^4.0.1"
86
+ "@capacitor/android": "^4.7.2",
87
+ "@capacitor/app": "^4.1.1",
88
+ "@capacitor/core": "^4.7.2",
89
+ "@capacitor/ios": "^4.7.2"
90
90
  },
91
91
  "scripts": {
92
92
  "clean": "rimraf dist",
@@ -1,15 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
- xmlns:app="http://schemas.android.com/apk/res-auto"
4
- xmlns:tools="http://schemas.android.com/tools"
5
- android:layout_width="match_parent"
6
- android:layout_height="match_parent"
7
- tools:context="com.getcapacitor.BridgeActivity"
8
- >
9
-
10
- <WebView
11
- android:id="@+id/webview"
12
- android:layout_width="fill_parent"
13
- android:layout_height="fill_parent" />
14
-
15
- </androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -1,28 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <navigation xmlns:android="http://schemas.android.com/apk/res/android"
3
- xmlns:app="http://schemas.android.com/apk/res-auto"
4
- xmlns:tools="http://schemas.android.com/tools"
5
- android:id="@+id/nav_graph"
6
- app:startDestination="@id/FirstFragment">
7
-
8
- <fragment
9
- android:id="@+id/FirstFragment"
10
- android:name="com.epicshaggy.biometric.FirstFragment"
11
- android:label="@string/first_fragment_label"
12
- tools:layout="@layout/fragment_first">
13
-
14
- <action
15
- android:id="@+id/action_FirstFragment_to_SecondFragment"
16
- app:destination="@id/SecondFragment" />
17
- </fragment>
18
- <fragment
19
- android:id="@+id/SecondFragment"
20
- android:name="com.epicshaggy.biometric.SecondFragment"
21
- android:label="@string/second_fragment_label"
22
- tools:layout="@layout/fragment_second">
23
-
24
- <action
25
- android:id="@+id/action_SecondFragment_to_FirstFragment"
26
- app:destination="@id/FirstFragment" />
27
- </fragment>
28
- </navigation>
@@ -1,3 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <resources>
3
- </resources>
@@ -1,3 +0,0 @@
1
- <resources>
2
- <dimen name="fab_margin">16dp</dimen>
3
- </resources>