capacitor-biometric-authentication
Version:
Framework-agnostic biometric authentication library. Works with React, Vue, Angular, or vanilla JS. No providers required!
162 lines • 5.64 kB
JavaScript
import { BiometricErrorCode, BiometryType } from '../core/types';
export class ReactNativeAdapter {
constructor() {
this.platform = 'react-native';
// Biometrics module will be loaded dynamically
}
async getBiometrics() {
if (this.biometrics) {
return this.biometrics;
}
try {
// Dynamic import for React Native biometrics
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
const ReactNativeBiometrics = require('react-native-biometrics').default;
this.biometrics = new ReactNativeBiometrics();
return this.biometrics;
}
catch (_a) {
throw new Error('React Native Biometrics not installed. Please run: npm install react-native-biometrics');
}
}
async isAvailable() {
try {
const biometrics = await this.getBiometrics();
const { available } = await biometrics.isSensorAvailable();
return available;
}
catch (_a) {
return false;
}
}
async getSupportedBiometrics() {
try {
const biometrics = await this.getBiometrics();
const { available, biometryType } = await biometrics.isSensorAvailable();
if (!available) {
return [];
}
// Map React Native biometry types to our types
switch (biometryType) {
case 'TouchID':
return [BiometryType.TOUCH_ID];
case 'FaceID':
return [BiometryType.FACE_ID];
case 'Biometrics':
case 'Fingerprint':
return [BiometryType.FINGERPRINT];
default:
return [BiometryType.UNKNOWN];
}
}
catch (_a) {
return [];
}
}
async authenticate(options) {
try {
const biometrics = await this.getBiometrics();
// Check if biometrics are available
const { available, biometryType, error } = await biometrics.isSensorAvailable();
if (!available) {
return {
success: false,
error: {
code: BiometricErrorCode.BIOMETRIC_UNAVAILABLE,
message: error || 'Biometric authentication is not available'
}
};
}
// Create signature for authentication
const { success, signature, error: authError } = await biometrics.createSignature({
promptMessage: (options === null || options === void 0 ? void 0 : options.reason) || 'Authenticate',
cancelButtonText: (options === null || options === void 0 ? void 0 : options.cancelTitle) || 'Cancel',
payload: 'biometric-auth-payload'
});
if (success && signature) {
return {
success: true,
biometryType: this.mapBiometryType(biometryType),
sessionId: this.generateSessionId(),
platform: 'react-native'
};
}
else {
return {
success: false,
error: this.mapError(authError)
};
}
}
catch (error) {
return {
success: false,
error: this.mapError(error)
};
}
}
async deleteCredentials() {
try {
const biometrics = await this.getBiometrics();
await biometrics.deleteKeys();
}
catch (_a) {
// Ignore errors when deleting credentials
}
}
async hasCredentials() {
try {
const biometrics = await this.getBiometrics();
const { keysExist } = await biometrics.biometricKeysExist();
return keysExist;
}
catch (_a) {
return false;
}
}
mapBiometryType(type) {
if (!type) {
return BiometryType.UNKNOWN;
}
switch (type) {
case 'TouchID':
return BiometryType.TOUCH_ID;
case 'FaceID':
return BiometryType.FACE_ID;
case 'Biometrics':
case 'Fingerprint':
return BiometryType.FINGERPRINT;
default:
return BiometryType.UNKNOWN;
}
}
mapError(error) {
let code = BiometricErrorCode.UNKNOWN_ERROR;
let message = 'An unknown error occurred';
if (typeof error === 'string') {
message = error;
// Map common error messages to error codes
if (error.includes('cancelled') || error.includes('canceled')) {
code = BiometricErrorCode.USER_CANCELLED;
}
else if (error.includes('failed') || error.includes('not recognized')) {
code = BiometricErrorCode.AUTHENTICATION_FAILED;
}
else if (error.includes('locked')) {
code = BiometricErrorCode.LOCKOUT;
}
}
else if (error instanceof Error) {
message = error.message;
}
return {
code,
message,
details: error
};
}
generateSessionId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
}
//# sourceMappingURL=ReactNativeAdapter.js.map