@aparajita/capacitor-biometric-auth 8.0.2 → 9.1.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/AparajitaCapacitorBiometricAuth.podspec +1 -1
- package/README.md +31 -75
- package/android/build.gradle +13 -11
- package/android/src/main/java/com/aparajita/capacitor/biometricauth/AuthActivity.java +1 -1
- package/android/src/main/java/com/aparajita/capacitor/biometricauth/BiometricAuthNative.java +4 -2
- package/dist/esm/base.d.ts +2 -2
- package/dist/esm/base.js +15 -12
- package/dist/esm/definitions.d.ts +2 -2
- package/dist/esm/definitions.js +11 -2
- package/dist/esm/index.js +12 -3
- package/dist/esm/native.d.ts +4 -4
- package/dist/esm/native.js +11 -8
- package/dist/esm/web-utils.js +0 -1
- package/dist/esm/web.js +24 -29
- package/dist/plugin.cjs.js +72 -54
- package/dist/plugin.js +72 -54
- package/ios/Plugin/Plugin.swift +8 -1
- package/package.json +75 -47
- package/ios/Plugin/Plugin.h +0 -10
- package/ios/Plugin/Plugin.m +0 -7
package/dist/plugin.cjs.js
CHANGED
|
@@ -66,13 +66,22 @@ exports.BiometryErrorType = void 0;
|
|
|
66
66
|
BiometryErrorType["biometryNotEnrolled"] = "biometryNotEnrolled";
|
|
67
67
|
BiometryErrorType["noDeviceCredential"] = "noDeviceCredential";
|
|
68
68
|
})(exports.BiometryErrorType || (exports.BiometryErrorType = {}));
|
|
69
|
+
function isBiometryErrorType(value) {
|
|
70
|
+
return (typeof value === 'string' &&
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
72
|
+
Object.values(exports.BiometryErrorType).includes(value));
|
|
73
|
+
}
|
|
69
74
|
/**
|
|
70
75
|
* `authenticate()` throws instances of this class.
|
|
71
76
|
*/
|
|
72
|
-
class BiometryError {
|
|
77
|
+
class BiometryError extends Error {
|
|
73
78
|
constructor(message, code) {
|
|
74
|
-
|
|
79
|
+
super(message);
|
|
75
80
|
this.code = code;
|
|
81
|
+
this.name = 'BiometryError';
|
|
82
|
+
// Set the prototype explicitly to ensure instanceof works correctly.
|
|
83
|
+
// This is recommended for custom error classes in TypeScript.
|
|
84
|
+
Object.setPrototypeOf(this, BiometryError.prototype);
|
|
76
85
|
}
|
|
77
86
|
}
|
|
78
87
|
|
|
@@ -87,15 +96,23 @@ const kBiometryTypeNameMap = {
|
|
|
87
96
|
/**
|
|
88
97
|
* Return a human-readable name for a BiometryType.
|
|
89
98
|
*/
|
|
90
|
-
// eslint-disable-next-line import/prefer-default-export
|
|
91
99
|
function getBiometryName(type) {
|
|
92
100
|
return kBiometryTypeNameMap[type] || '';
|
|
93
101
|
}
|
|
94
102
|
|
|
95
103
|
const proxy = core.registerPlugin('BiometricAuthNative', {
|
|
96
|
-
web: async () =>
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
web: async () => {
|
|
105
|
+
const module = await Promise.resolve().then(function () { return web; });
|
|
106
|
+
return new module.BiometricAuthWeb();
|
|
107
|
+
},
|
|
108
|
+
ios: async () => {
|
|
109
|
+
const module = await Promise.resolve().then(function () { return native; });
|
|
110
|
+
return new module.BiometricAuthNative(proxy);
|
|
111
|
+
},
|
|
112
|
+
android: async () => {
|
|
113
|
+
const module = await Promise.resolve().then(function () { return native; });
|
|
114
|
+
return new module.BiometricAuthNative(proxy);
|
|
115
|
+
},
|
|
99
116
|
});
|
|
100
117
|
|
|
101
118
|
class BiometricAuthBase extends core.WebPlugin {
|
|
@@ -106,28 +123,30 @@ class BiometricAuthBase extends core.WebPlugin {
|
|
|
106
123
|
catch (error) {
|
|
107
124
|
// error will be an instance of CapacitorException on native platforms,
|
|
108
125
|
// an instance of BiometryError on the web.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
throw error;
|
|
114
|
-
}
|
|
126
|
+
throw error instanceof core.CapacitorException &&
|
|
127
|
+
isBiometryErrorType(error.code)
|
|
128
|
+
? new BiometryError(error.message, error.code)
|
|
129
|
+
: error;
|
|
115
130
|
}
|
|
116
131
|
}
|
|
117
132
|
async addResumeListener(listener) {
|
|
118
133
|
return app.App.addListener('appStateChange', ({ isActive }) => {
|
|
119
134
|
if (isActive) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
135
|
+
(async () => {
|
|
136
|
+
try {
|
|
137
|
+
const info = await this.checkBiometry();
|
|
138
|
+
listener(info);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
console.error(error);
|
|
142
|
+
}
|
|
143
|
+
})();
|
|
125
144
|
}
|
|
126
145
|
});
|
|
127
146
|
}
|
|
128
147
|
}
|
|
129
148
|
|
|
130
|
-
|
|
149
|
+
/* eslint-disable @typescript-eslint/require-await */
|
|
131
150
|
class BiometricAuthWeb extends BiometricAuthBase {
|
|
132
151
|
constructor() {
|
|
133
152
|
super(...arguments);
|
|
@@ -150,7 +169,7 @@ class BiometricAuthWeb extends BiometricAuthBase {
|
|
|
150
169
|
reason = 'Biometry is not enrolled';
|
|
151
170
|
code = exports.BiometryErrorType.biometryNotEnrolled;
|
|
152
171
|
}
|
|
153
|
-
return
|
|
172
|
+
return {
|
|
154
173
|
isAvailable: available,
|
|
155
174
|
strongBiometryIsAvailable: this.biometryIsEnrolled && this.hasStrongBiometry(),
|
|
156
175
|
biometryType: this.biometryType,
|
|
@@ -158,38 +177,36 @@ class BiometricAuthWeb extends BiometricAuthBase {
|
|
|
158
177
|
deviceIsSecure: this.deviceIsSecure,
|
|
159
178
|
reason,
|
|
160
179
|
code,
|
|
161
|
-
}
|
|
180
|
+
};
|
|
162
181
|
}
|
|
163
182
|
hasStrongBiometry() {
|
|
164
183
|
return this.biometryTypes.some((type) => type === exports.BiometryType.faceId ||
|
|
165
184
|
type === exports.BiometryType.touchId ||
|
|
166
185
|
type === exports.BiometryType.fingerprintAuthentication);
|
|
167
186
|
}
|
|
168
|
-
/* eslint-disable no-alert */
|
|
169
187
|
// On the web, fake authentication with a confirm dialog.
|
|
170
188
|
async internalAuthenticate(options) {
|
|
171
189
|
const result = await this.checkBiometry();
|
|
172
190
|
// First try biometry if available.
|
|
173
|
-
if (result.isAvailable
|
|
174
|
-
|
|
191
|
+
if (result.isAvailable &&
|
|
192
|
+
// oxlint-disable-next-line no-alert
|
|
193
|
+
confirm(
|
|
175
194
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we want to use the default value if options?.reason is an empty string
|
|
176
195
|
(options === null || options === void 0 ? void 0 : options.reason) ||
|
|
177
196
|
`Authenticate with ${result.biometryTypes
|
|
178
197
|
.map((type) => getBiometryName(type))
|
|
179
198
|
.join(' or ')}?`)) {
|
|
180
|
-
|
|
181
|
-
}
|
|
199
|
+
return;
|
|
182
200
|
}
|
|
183
201
|
if (options === null || options === void 0 ? void 0 : options.allowDeviceCredential) {
|
|
184
202
|
// Either biometry is not available, or the user declined to use it
|
|
185
203
|
// and device security is allowed.
|
|
186
204
|
if (result.deviceIsSecure) {
|
|
205
|
+
// oxlint-disable-next-line no-alert
|
|
187
206
|
if (confirm('Authenticate with device security?')) {
|
|
188
207
|
return;
|
|
189
208
|
}
|
|
190
|
-
|
|
191
|
-
throw new BiometryError('User cancelled', exports.BiometryErrorType.userCancel);
|
|
192
|
-
}
|
|
209
|
+
throw new BiometryError('User cancelled', exports.BiometryErrorType.userCancel);
|
|
193
210
|
}
|
|
194
211
|
else if (result.isAvailable) {
|
|
195
212
|
throw new BiometryError('Device is not secure', exports.BiometryErrorType.noDeviceCredential);
|
|
@@ -197,12 +214,9 @@ class BiometricAuthWeb extends BiometricAuthBase {
|
|
|
197
214
|
}
|
|
198
215
|
else if (!result.isAvailable) {
|
|
199
216
|
// Biometry is not available and device security is not allowed.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
else {
|
|
204
|
-
throw new BiometryError('Biometry is not enrolled', exports.BiometryErrorType.biometryNotEnrolled);
|
|
205
|
-
}
|
|
217
|
+
throw result.biometryType === exports.BiometryType.none
|
|
218
|
+
? new BiometryError('Biometry is not available', exports.BiometryErrorType.biometryNotAvailable)
|
|
219
|
+
: new BiometryError('Biometry is not enrolled', exports.BiometryErrorType.biometryNotEnrolled);
|
|
206
220
|
}
|
|
207
221
|
// The user declined to use biometry and device credentials not allowed.
|
|
208
222
|
throw new BiometryError('User cancelled', exports.BiometryErrorType.userCancel);
|
|
@@ -210,13 +224,13 @@ class BiometricAuthWeb extends BiometricAuthBase {
|
|
|
210
224
|
// Web only, used for simulating biometric authentication.
|
|
211
225
|
async setBiometryType(type) {
|
|
212
226
|
if (type === undefined) {
|
|
213
|
-
return
|
|
227
|
+
return;
|
|
214
228
|
}
|
|
215
229
|
const types = Array.isArray(type) ? type : [type];
|
|
216
230
|
this.biometryTypes = [];
|
|
217
231
|
this.biometryType = exports.BiometryType.none;
|
|
218
232
|
if (types.length === 0) {
|
|
219
|
-
return
|
|
233
|
+
return;
|
|
220
234
|
}
|
|
221
235
|
if (isBiometryTypes(types)) {
|
|
222
236
|
this.biometryType = types[0];
|
|
@@ -225,46 +239,45 @@ class BiometricAuthWeb extends BiometricAuthBase {
|
|
|
225
239
|
}
|
|
226
240
|
}
|
|
227
241
|
else {
|
|
228
|
-
for (
|
|
229
|
-
|
|
230
|
-
if (exports.BiometryType.hasOwnProperty(types[i])) {
|
|
231
|
-
const biometryType = exports.BiometryType[types[i]];
|
|
242
|
+
for (const [i, theType] of types.entries()) {
|
|
243
|
+
if (isBiometryType(theType)) {
|
|
232
244
|
if (this.biometryType === exports.BiometryType.none) {
|
|
233
245
|
this.biometryTypes = [];
|
|
234
246
|
}
|
|
235
247
|
else {
|
|
236
|
-
this.biometryTypes.push(
|
|
248
|
+
this.biometryTypes.push(theType);
|
|
237
249
|
}
|
|
238
250
|
if (i === 0) {
|
|
239
|
-
this.biometryType =
|
|
251
|
+
this.biometryType = theType;
|
|
240
252
|
}
|
|
241
253
|
}
|
|
242
254
|
}
|
|
243
255
|
}
|
|
244
|
-
return Promise.resolve();
|
|
245
256
|
}
|
|
246
257
|
// Web only, used for simulating device unlock security.
|
|
247
258
|
async setBiometryIsEnrolled(enrolled) {
|
|
248
259
|
this.biometryIsEnrolled = enrolled;
|
|
249
|
-
return Promise.resolve();
|
|
250
260
|
}
|
|
251
261
|
// Web only, used for simulating device unlock security.
|
|
252
262
|
async setDeviceIsSecure(isSecure) {
|
|
253
263
|
this.deviceIsSecure = isSecure;
|
|
254
|
-
return Promise.resolve();
|
|
255
264
|
}
|
|
256
265
|
}
|
|
266
|
+
function isBiometryType(value) {
|
|
267
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
268
|
+
return Object.values(exports.BiometryType).includes(value);
|
|
269
|
+
}
|
|
257
270
|
function isBiometryTypes(value) {
|
|
258
|
-
return
|
|
271
|
+
return value.every((type) => isBiometryType(type));
|
|
259
272
|
}
|
|
273
|
+
/* eslint-enable @typescript-eslint/require-await */
|
|
260
274
|
|
|
261
275
|
var web = /*#__PURE__*/Object.freeze({
|
|
262
276
|
__proto__: null,
|
|
263
277
|
BiometricAuthWeb: BiometricAuthWeb
|
|
264
278
|
});
|
|
265
279
|
|
|
266
|
-
/* eslint-disable @typescript-eslint/
|
|
267
|
-
// eslint-disable-next-line import/prefer-default-export
|
|
280
|
+
/* eslint-disable @typescript-eslint/class-methods-use-this, @typescript-eslint/require-await */
|
|
268
281
|
class BiometricAuthNative extends BiometricAuthBase {
|
|
269
282
|
constructor(capProxy) {
|
|
270
283
|
super();
|
|
@@ -276,6 +289,7 @@ class BiometricAuthNative extends BiometricAuthBase {
|
|
|
276
289
|
capProxy is a proxy of an instance of this class, so it is safe
|
|
277
290
|
to cast it to this class.
|
|
278
291
|
*/
|
|
292
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
279
293
|
const proxy = capProxy;
|
|
280
294
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
281
295
|
this.checkBiometry = proxy.checkBiometry;
|
|
@@ -285,7 +299,7 @@ class BiometricAuthNative extends BiometricAuthBase {
|
|
|
285
299
|
// @native
|
|
286
300
|
async checkBiometry() {
|
|
287
301
|
// Never used, but we have to satisfy the compiler.
|
|
288
|
-
return
|
|
302
|
+
return {
|
|
289
303
|
isAvailable: false,
|
|
290
304
|
strongBiometryIsAvailable: false,
|
|
291
305
|
biometryType: exports.BiometryType.none,
|
|
@@ -295,24 +309,27 @@ class BiometricAuthNative extends BiometricAuthBase {
|
|
|
295
309
|
code: exports.BiometryErrorType.none,
|
|
296
310
|
strongReason: '',
|
|
297
311
|
strongCode: exports.BiometryErrorType.none,
|
|
298
|
-
}
|
|
312
|
+
};
|
|
299
313
|
}
|
|
300
314
|
// @native
|
|
301
315
|
// On native platforms, this will present the native authentication UI.
|
|
302
|
-
async internalAuthenticate(
|
|
316
|
+
async internalAuthenticate(_options) {
|
|
317
|
+
// This method is implemented natively
|
|
318
|
+
}
|
|
303
319
|
// Web only, used for simulating biometric authentication.
|
|
304
|
-
async setBiometryType(
|
|
320
|
+
async setBiometryType(_type) {
|
|
305
321
|
console.warn('setBiometryType() is web only');
|
|
306
322
|
}
|
|
307
323
|
// Web only, used for simulating biometry enrollment.
|
|
308
|
-
async setBiometryIsEnrolled(
|
|
324
|
+
async setBiometryIsEnrolled(_enrolled) {
|
|
309
325
|
console.warn('setBiometryEnrolled() is web only');
|
|
310
326
|
}
|
|
311
327
|
// Web only, used for simulating device security.
|
|
312
|
-
async setDeviceIsSecure(
|
|
328
|
+
async setDeviceIsSecure(_isSecure) {
|
|
313
329
|
console.warn('setDeviceIsSecure() is web only');
|
|
314
330
|
}
|
|
315
331
|
}
|
|
332
|
+
/* eslint-enable @typescript-eslint/class-methods-use-this, @typescript-eslint/require-await */
|
|
316
333
|
|
|
317
334
|
var native = /*#__PURE__*/Object.freeze({
|
|
318
335
|
__proto__: null,
|
|
@@ -322,3 +339,4 @@ var native = /*#__PURE__*/Object.freeze({
|
|
|
322
339
|
exports.BiometricAuth = proxy;
|
|
323
340
|
exports.BiometryError = BiometryError;
|
|
324
341
|
exports.getBiometryName = getBiometryName;
|
|
342
|
+
exports.isBiometryErrorType = isBiometryErrorType;
|
package/dist/plugin.js
CHANGED
|
@@ -64,13 +64,22 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
64
64
|
BiometryErrorType["biometryNotEnrolled"] = "biometryNotEnrolled";
|
|
65
65
|
BiometryErrorType["noDeviceCredential"] = "noDeviceCredential";
|
|
66
66
|
})(exports.BiometryErrorType || (exports.BiometryErrorType = {}));
|
|
67
|
+
function isBiometryErrorType(value) {
|
|
68
|
+
return (typeof value === 'string' &&
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
70
|
+
Object.values(exports.BiometryErrorType).includes(value));
|
|
71
|
+
}
|
|
67
72
|
/**
|
|
68
73
|
* `authenticate()` throws instances of this class.
|
|
69
74
|
*/
|
|
70
|
-
class BiometryError {
|
|
75
|
+
class BiometryError extends Error {
|
|
71
76
|
constructor(message, code) {
|
|
72
|
-
|
|
77
|
+
super(message);
|
|
73
78
|
this.code = code;
|
|
79
|
+
this.name = 'BiometryError';
|
|
80
|
+
// Set the prototype explicitly to ensure instanceof works correctly.
|
|
81
|
+
// This is recommended for custom error classes in TypeScript.
|
|
82
|
+
Object.setPrototypeOf(this, BiometryError.prototype);
|
|
74
83
|
}
|
|
75
84
|
}
|
|
76
85
|
|
|
@@ -85,15 +94,23 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
85
94
|
/**
|
|
86
95
|
* Return a human-readable name for a BiometryType.
|
|
87
96
|
*/
|
|
88
|
-
// eslint-disable-next-line import/prefer-default-export
|
|
89
97
|
function getBiometryName(type) {
|
|
90
98
|
return kBiometryTypeNameMap[type] || '';
|
|
91
99
|
}
|
|
92
100
|
|
|
93
101
|
const proxy = core.registerPlugin('BiometricAuthNative', {
|
|
94
|
-
web: async () =>
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
web: async () => {
|
|
103
|
+
const module = await Promise.resolve().then(function () { return web; });
|
|
104
|
+
return new module.BiometricAuthWeb();
|
|
105
|
+
},
|
|
106
|
+
ios: async () => {
|
|
107
|
+
const module = await Promise.resolve().then(function () { return native; });
|
|
108
|
+
return new module.BiometricAuthNative(proxy);
|
|
109
|
+
},
|
|
110
|
+
android: async () => {
|
|
111
|
+
const module = await Promise.resolve().then(function () { return native; });
|
|
112
|
+
return new module.BiometricAuthNative(proxy);
|
|
113
|
+
},
|
|
97
114
|
});
|
|
98
115
|
|
|
99
116
|
class BiometricAuthBase extends core.WebPlugin {
|
|
@@ -104,28 +121,30 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
104
121
|
catch (error) {
|
|
105
122
|
// error will be an instance of CapacitorException on native platforms,
|
|
106
123
|
// an instance of BiometryError on the web.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
throw error;
|
|
112
|
-
}
|
|
124
|
+
throw error instanceof core.CapacitorException &&
|
|
125
|
+
isBiometryErrorType(error.code)
|
|
126
|
+
? new BiometryError(error.message, error.code)
|
|
127
|
+
: error;
|
|
113
128
|
}
|
|
114
129
|
}
|
|
115
130
|
async addResumeListener(listener) {
|
|
116
131
|
return app.App.addListener('appStateChange', ({ isActive }) => {
|
|
117
132
|
if (isActive) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
133
|
+
(async () => {
|
|
134
|
+
try {
|
|
135
|
+
const info = await this.checkBiometry();
|
|
136
|
+
listener(info);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
console.error(error);
|
|
140
|
+
}
|
|
141
|
+
})();
|
|
123
142
|
}
|
|
124
143
|
});
|
|
125
144
|
}
|
|
126
145
|
}
|
|
127
146
|
|
|
128
|
-
|
|
147
|
+
/* eslint-disable @typescript-eslint/require-await */
|
|
129
148
|
class BiometricAuthWeb extends BiometricAuthBase {
|
|
130
149
|
constructor() {
|
|
131
150
|
super(...arguments);
|
|
@@ -148,7 +167,7 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
148
167
|
reason = 'Biometry is not enrolled';
|
|
149
168
|
code = exports.BiometryErrorType.biometryNotEnrolled;
|
|
150
169
|
}
|
|
151
|
-
return
|
|
170
|
+
return {
|
|
152
171
|
isAvailable: available,
|
|
153
172
|
strongBiometryIsAvailable: this.biometryIsEnrolled && this.hasStrongBiometry(),
|
|
154
173
|
biometryType: this.biometryType,
|
|
@@ -156,38 +175,36 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
156
175
|
deviceIsSecure: this.deviceIsSecure,
|
|
157
176
|
reason,
|
|
158
177
|
code,
|
|
159
|
-
}
|
|
178
|
+
};
|
|
160
179
|
}
|
|
161
180
|
hasStrongBiometry() {
|
|
162
181
|
return this.biometryTypes.some((type) => type === exports.BiometryType.faceId ||
|
|
163
182
|
type === exports.BiometryType.touchId ||
|
|
164
183
|
type === exports.BiometryType.fingerprintAuthentication);
|
|
165
184
|
}
|
|
166
|
-
/* eslint-disable no-alert */
|
|
167
185
|
// On the web, fake authentication with a confirm dialog.
|
|
168
186
|
async internalAuthenticate(options) {
|
|
169
187
|
const result = await this.checkBiometry();
|
|
170
188
|
// First try biometry if available.
|
|
171
|
-
if (result.isAvailable
|
|
172
|
-
|
|
189
|
+
if (result.isAvailable &&
|
|
190
|
+
// oxlint-disable-next-line no-alert
|
|
191
|
+
confirm(
|
|
173
192
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we want to use the default value if options?.reason is an empty string
|
|
174
193
|
(options === null || options === void 0 ? void 0 : options.reason) ||
|
|
175
194
|
`Authenticate with ${result.biometryTypes
|
|
176
195
|
.map((type) => getBiometryName(type))
|
|
177
196
|
.join(' or ')}?`)) {
|
|
178
|
-
|
|
179
|
-
}
|
|
197
|
+
return;
|
|
180
198
|
}
|
|
181
199
|
if (options === null || options === void 0 ? void 0 : options.allowDeviceCredential) {
|
|
182
200
|
// Either biometry is not available, or the user declined to use it
|
|
183
201
|
// and device security is allowed.
|
|
184
202
|
if (result.deviceIsSecure) {
|
|
203
|
+
// oxlint-disable-next-line no-alert
|
|
185
204
|
if (confirm('Authenticate with device security?')) {
|
|
186
205
|
return;
|
|
187
206
|
}
|
|
188
|
-
|
|
189
|
-
throw new BiometryError('User cancelled', exports.BiometryErrorType.userCancel);
|
|
190
|
-
}
|
|
207
|
+
throw new BiometryError('User cancelled', exports.BiometryErrorType.userCancel);
|
|
191
208
|
}
|
|
192
209
|
else if (result.isAvailable) {
|
|
193
210
|
throw new BiometryError('Device is not secure', exports.BiometryErrorType.noDeviceCredential);
|
|
@@ -195,12 +212,9 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
195
212
|
}
|
|
196
213
|
else if (!result.isAvailable) {
|
|
197
214
|
// Biometry is not available and device security is not allowed.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
else {
|
|
202
|
-
throw new BiometryError('Biometry is not enrolled', exports.BiometryErrorType.biometryNotEnrolled);
|
|
203
|
-
}
|
|
215
|
+
throw result.biometryType === exports.BiometryType.none
|
|
216
|
+
? new BiometryError('Biometry is not available', exports.BiometryErrorType.biometryNotAvailable)
|
|
217
|
+
: new BiometryError('Biometry is not enrolled', exports.BiometryErrorType.biometryNotEnrolled);
|
|
204
218
|
}
|
|
205
219
|
// The user declined to use biometry and device credentials not allowed.
|
|
206
220
|
throw new BiometryError('User cancelled', exports.BiometryErrorType.userCancel);
|
|
@@ -208,13 +222,13 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
208
222
|
// Web only, used for simulating biometric authentication.
|
|
209
223
|
async setBiometryType(type) {
|
|
210
224
|
if (type === undefined) {
|
|
211
|
-
return
|
|
225
|
+
return;
|
|
212
226
|
}
|
|
213
227
|
const types = Array.isArray(type) ? type : [type];
|
|
214
228
|
this.biometryTypes = [];
|
|
215
229
|
this.biometryType = exports.BiometryType.none;
|
|
216
230
|
if (types.length === 0) {
|
|
217
|
-
return
|
|
231
|
+
return;
|
|
218
232
|
}
|
|
219
233
|
if (isBiometryTypes(types)) {
|
|
220
234
|
this.biometryType = types[0];
|
|
@@ -223,46 +237,45 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
223
237
|
}
|
|
224
238
|
}
|
|
225
239
|
else {
|
|
226
|
-
for (
|
|
227
|
-
|
|
228
|
-
if (exports.BiometryType.hasOwnProperty(types[i])) {
|
|
229
|
-
const biometryType = exports.BiometryType[types[i]];
|
|
240
|
+
for (const [i, theType] of types.entries()) {
|
|
241
|
+
if (isBiometryType(theType)) {
|
|
230
242
|
if (this.biometryType === exports.BiometryType.none) {
|
|
231
243
|
this.biometryTypes = [];
|
|
232
244
|
}
|
|
233
245
|
else {
|
|
234
|
-
this.biometryTypes.push(
|
|
246
|
+
this.biometryTypes.push(theType);
|
|
235
247
|
}
|
|
236
248
|
if (i === 0) {
|
|
237
|
-
this.biometryType =
|
|
249
|
+
this.biometryType = theType;
|
|
238
250
|
}
|
|
239
251
|
}
|
|
240
252
|
}
|
|
241
253
|
}
|
|
242
|
-
return Promise.resolve();
|
|
243
254
|
}
|
|
244
255
|
// Web only, used for simulating device unlock security.
|
|
245
256
|
async setBiometryIsEnrolled(enrolled) {
|
|
246
257
|
this.biometryIsEnrolled = enrolled;
|
|
247
|
-
return Promise.resolve();
|
|
248
258
|
}
|
|
249
259
|
// Web only, used for simulating device unlock security.
|
|
250
260
|
async setDeviceIsSecure(isSecure) {
|
|
251
261
|
this.deviceIsSecure = isSecure;
|
|
252
|
-
return Promise.resolve();
|
|
253
262
|
}
|
|
254
263
|
}
|
|
264
|
+
function isBiometryType(value) {
|
|
265
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
266
|
+
return Object.values(exports.BiometryType).includes(value);
|
|
267
|
+
}
|
|
255
268
|
function isBiometryTypes(value) {
|
|
256
|
-
return
|
|
269
|
+
return value.every((type) => isBiometryType(type));
|
|
257
270
|
}
|
|
271
|
+
/* eslint-enable @typescript-eslint/require-await */
|
|
258
272
|
|
|
259
273
|
var web = /*#__PURE__*/Object.freeze({
|
|
260
274
|
__proto__: null,
|
|
261
275
|
BiometricAuthWeb: BiometricAuthWeb
|
|
262
276
|
});
|
|
263
277
|
|
|
264
|
-
/* eslint-disable @typescript-eslint/
|
|
265
|
-
// eslint-disable-next-line import/prefer-default-export
|
|
278
|
+
/* eslint-disable @typescript-eslint/class-methods-use-this, @typescript-eslint/require-await */
|
|
266
279
|
class BiometricAuthNative extends BiometricAuthBase {
|
|
267
280
|
constructor(capProxy) {
|
|
268
281
|
super();
|
|
@@ -274,6 +287,7 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
274
287
|
capProxy is a proxy of an instance of this class, so it is safe
|
|
275
288
|
to cast it to this class.
|
|
276
289
|
*/
|
|
290
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
277
291
|
const proxy = capProxy;
|
|
278
292
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
279
293
|
this.checkBiometry = proxy.checkBiometry;
|
|
@@ -283,7 +297,7 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
283
297
|
// @native
|
|
284
298
|
async checkBiometry() {
|
|
285
299
|
// Never used, but we have to satisfy the compiler.
|
|
286
|
-
return
|
|
300
|
+
return {
|
|
287
301
|
isAvailable: false,
|
|
288
302
|
strongBiometryIsAvailable: false,
|
|
289
303
|
biometryType: exports.BiometryType.none,
|
|
@@ -293,24 +307,27 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
293
307
|
code: exports.BiometryErrorType.none,
|
|
294
308
|
strongReason: '',
|
|
295
309
|
strongCode: exports.BiometryErrorType.none,
|
|
296
|
-
}
|
|
310
|
+
};
|
|
297
311
|
}
|
|
298
312
|
// @native
|
|
299
313
|
// On native platforms, this will present the native authentication UI.
|
|
300
|
-
async internalAuthenticate(
|
|
314
|
+
async internalAuthenticate(_options) {
|
|
315
|
+
// This method is implemented natively
|
|
316
|
+
}
|
|
301
317
|
// Web only, used for simulating biometric authentication.
|
|
302
|
-
async setBiometryType(
|
|
318
|
+
async setBiometryType(_type) {
|
|
303
319
|
console.warn('setBiometryType() is web only');
|
|
304
320
|
}
|
|
305
321
|
// Web only, used for simulating biometry enrollment.
|
|
306
|
-
async setBiometryIsEnrolled(
|
|
322
|
+
async setBiometryIsEnrolled(_enrolled) {
|
|
307
323
|
console.warn('setBiometryEnrolled() is web only');
|
|
308
324
|
}
|
|
309
325
|
// Web only, used for simulating device security.
|
|
310
|
-
async setDeviceIsSecure(
|
|
326
|
+
async setDeviceIsSecure(_isSecure) {
|
|
311
327
|
console.warn('setDeviceIsSecure() is web only');
|
|
312
328
|
}
|
|
313
329
|
}
|
|
330
|
+
/* eslint-enable @typescript-eslint/class-methods-use-this, @typescript-eslint/require-await */
|
|
314
331
|
|
|
315
332
|
var native = /*#__PURE__*/Object.freeze({
|
|
316
333
|
__proto__: null,
|
|
@@ -320,6 +337,7 @@ var capacitorBiometricAuth = (function (exports, core, app) {
|
|
|
320
337
|
exports.BiometricAuth = proxy;
|
|
321
338
|
exports.BiometryError = BiometryError;
|
|
322
339
|
exports.getBiometryName = getBiometryName;
|
|
340
|
+
exports.isBiometryErrorType = isBiometryErrorType;
|
|
323
341
|
|
|
324
342
|
return exports;
|
|
325
343
|
|
package/ios/Plugin/Plugin.swift
CHANGED
|
@@ -6,7 +6,14 @@ private let kReason = "reason"
|
|
|
6
6
|
private let kMissingFaceIDUsageEntry = "The device supports Face ID, but NSFaceIDUsageDescription is not in Info.plist."
|
|
7
7
|
|
|
8
8
|
@objc(BiometricAuthNative)
|
|
9
|
-
public class BiometricAuthNative: CAPPlugin {
|
|
9
|
+
public class BiometricAuthNative: CAPPlugin, CAPBridgedPlugin {
|
|
10
|
+
public let identifier = "BiometricAuthNative"
|
|
11
|
+
public let jsName = "BiometricAuthNative"
|
|
12
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
13
|
+
.init(#selector(checkBiometry)),
|
|
14
|
+
.init(#selector(internalAuthenticate))
|
|
15
|
+
]
|
|
16
|
+
|
|
10
17
|
let biometryErrorCodeMap: [Int: String] = [
|
|
11
18
|
0: "",
|
|
12
19
|
LAError.appCancel.rawValue: "appCancel",
|