UNPKG

capacitor-biometric-authentication

Version:

Framework-agnostic biometric authentication library. Works with React, Vue, Angular, or vanilla JS. No providers required!

208 lines 8.5 kB
import { BiometricErrorCode, BiometryType } from '../core/types'; export class CapacitorAdapter { constructor() { this.platform = 'capacitor'; // Plugin will be loaded dynamically } async getPlugin() { if (this.capacitorPlugin) { return this.capacitorPlugin; } try { // Try to get the registered Capacitor plugin const capacitorCore = await import('@capacitor/core'); // Try using registerPlugin if available if (capacitorCore.registerPlugin) { try { this.capacitorPlugin = capacitorCore.registerPlugin('BiometricAuth'); if (this.capacitorPlugin) { return this.capacitorPlugin; } } catch (_a) { // Continue to fallback } } // Legacy support for older Capacitor versions const legacyPlugins = capacitorCore.Plugins; if (legacyPlugins === null || legacyPlugins === void 0 ? void 0 : legacyPlugins.BiometricAuth) { this.capacitorPlugin = legacyPlugins.BiometricAuth; return this.capacitorPlugin; } // If not found in Plugins, try direct import // This allows the plugin to work even if not properly registered const BiometricAuthPlugin = window.BiometricAuthPlugin; if (BiometricAuthPlugin) { this.capacitorPlugin = BiometricAuthPlugin; return this.capacitorPlugin; } throw new Error('BiometricAuth Capacitor plugin not found'); } catch (error) { throw new Error('Failed to load Capacitor plugin: ' + error.message); } } async isAvailable() { try { const plugin = await this.getPlugin(); const result = await plugin.isAvailable(); return result.isAvailable || false; } catch (_a) { return false; } } async getSupportedBiometrics() { try { const plugin = await this.getPlugin(); const result = await plugin.getSupportedBiometrics(); // Map Capacitor biometry types to our types return (result.biometryTypes || []).map((type) => { switch (type.toLowerCase()) { case 'fingerprint': return BiometryType.FINGERPRINT; case 'faceid': case 'face_id': return BiometryType.FACE_ID; case 'touchid': case 'touch_id': return BiometryType.TOUCH_ID; case 'iris': return BiometryType.IRIS; default: return BiometryType.UNKNOWN; } }).filter((type) => type !== BiometryType.UNKNOWN); } catch (_a) { return []; } } async authenticate(options) { var _a, _b; try { const plugin = await this.getPlugin(); // Map our options to Capacitor plugin options const capacitorOptions = Object.assign(Object.assign({ reason: (options === null || options === void 0 ? void 0 : options.reason) || 'Authenticate to continue', cancelTitle: options === null || options === void 0 ? void 0 : options.cancelTitle, fallbackTitle: options === null || options === void 0 ? void 0 : options.fallbackTitle, disableDeviceCredential: options === null || options === void 0 ? void 0 : options.disableDeviceCredential, maxAttempts: options === null || options === void 0 ? void 0 : options.maxAttempts, requireConfirmation: options === null || options === void 0 ? void 0 : options.requireConfirmation }, (((_a = options === null || options === void 0 ? void 0 : options.platform) === null || _a === void 0 ? void 0 : _a.android) || {})), (((_b = options === null || options === void 0 ? void 0 : options.platform) === null || _b === void 0 ? void 0 : _b.ios) || {})); const result = await plugin.authenticate(capacitorOptions); if (result.success) { const biometryType = this.mapBiometryType(result.biometryType); return { success: true, biometryType, sessionId: this.generateSessionId(), platform: 'capacitor' }; } else { return { success: false, error: this.mapError(result.error) }; } } catch (error) { return { success: false, error: this.mapError(error) }; } } async deleteCredentials() { try { const plugin = await this.getPlugin(); await plugin.deleteCredentials(); } catch (_a) { // Ignore errors when deleting credentials } } async hasCredentials() { try { const plugin = await this.getPlugin(); // Check if the plugin has a hasCredentials method if (typeof plugin.hasCredentials === 'function') { const result = await plugin.hasCredentials(); return result.hasCredentials || false; } // Fallback: assume credentials exist if biometrics are available return await this.isAvailable(); } catch (_a) { return false; } } mapBiometryType(type) { if (!type) { return BiometryType.UNKNOWN; } switch (type.toLowerCase()) { case 'fingerprint': return BiometryType.FINGERPRINT; case 'faceid': case 'face_id': return BiometryType.FACE_ID; case 'touchid': case 'touch_id': return BiometryType.TOUCH_ID; case 'iris': return BiometryType.IRIS; default: return BiometryType.UNKNOWN; } } mapError(error) { let code = BiometricErrorCode.UNKNOWN_ERROR; let message = 'An unknown error occurred'; const errorObj = error; if (errorObj === null || errorObj === void 0 ? void 0 : errorObj.code) { switch (errorObj.code) { case 'BIOMETRIC_UNAVAILABLE': case 'UNAVAILABLE': code = BiometricErrorCode.BIOMETRIC_UNAVAILABLE; message = errorObj.message || 'Biometric authentication is not available'; break; case 'USER_CANCELLED': case 'CANCELLED': case 'USER_CANCEL': code = BiometricErrorCode.USER_CANCELLED; message = errorObj.message || 'User cancelled authentication'; break; case 'AUTHENTICATION_FAILED': case 'FAILED': code = BiometricErrorCode.AUTHENTICATION_FAILED; message = errorObj.message || 'Authentication failed'; break; case 'TIMEOUT': code = BiometricErrorCode.TIMEOUT; message = errorObj.message || 'Authentication timed out'; break; case 'LOCKOUT': code = BiometricErrorCode.LOCKOUT; message = errorObj.message || 'Too many failed attempts'; break; case 'NOT_ENROLLED': code = BiometricErrorCode.NOT_ENROLLED; message = errorObj.message || 'No biometric credentials enrolled'; break; default: message = errorObj.message || message; } } else if (error instanceof Error) { message = error.message; } else if (typeof error === 'string') { message = error; } return { code, message, details: error }; } generateSessionId() { return Date.now().toString(36) + Math.random().toString(36).substr(2); } } //# sourceMappingURL=CapacitorAdapter.js.map