UNPKG

react-native-biometrics-authentication

Version:

React Native biometric functionality for signing and encryption with optional fallback passcode option in IOS.

308 lines (270 loc) 10.5 kB
import { NativeModules } from "react-native"; const { ReactNativeBiometrics: bridge } = NativeModules; /** * Type alias for possible biometry types */ export type BiometryType = "TouchID" | "FaceID" | "Biometrics"; interface RNBiometricsOptions { allowDeviceCredentials?: boolean; } interface IsSensorAvailableResult { available: boolean; biometryType?: BiometryType; error?: string; } interface CreateKeysResult { publicKey: string; } interface BiometricKeysExistResult { keysExist: boolean; } interface DeleteKeysResult { keysDeleted: boolean; } interface CreateSignatureOptions { promptMessage: string; payload: string; cancelButtonText?: string; } interface CreateSignatureResult { success: boolean; signature?: string; error?: string; } interface SimplePromptOptions { promptMessage: string; fallbackPromptMessage?: string; cancelButtonText?: string; } interface AuthenticationOptions { promptMessage: string; fallbackPromptMessage?: string; cancelButtonText?: string; errorCallback: Function; successCallback: Function; encryption: boolean; } interface SimplePromptResult { success: boolean; error?: string; } interface AuthenticationResult { publicKey?: string; error?: string; } interface ERROR_TYPE {} /** * Enum for touch id sensor type */ export const TouchID = "TouchID"; /** * Enum for face id sensor type */ export const FaceID = "FaceID"; /** * Enum for generic biometrics (this is the only value available on android) */ export const Biometrics = "Biometrics"; /** * List of Biometrices Error Comes. */ export const BIOMETRY_ERROR_TYPE: ERROR_TYPE = { limitExceed: "Too many attempts. Try again later.", sensorDisable: "Too many attempts. Fingerprint sensor disabled.", signatureInvalidate: "Error generating signature", fingerPrintDisabled: "Your Finger Print is Locked.", }; /** * List of Biometrices Error Comes during enrollement. */ export const BIOMETRY_ENROLLED_ERROR_TYPE: ERROR_TYPE = { biometricNotEnroll: "BIOMETRIC_ERROR_NONE_ENROLLED", biometricNotSupport: "BIOMETRIC_ERROR_NO_HARDWARE", biometricHWUnavailable: "BIOMETRIC_ERROR_HW_UNAVAILABLE", biometricPasscodeNotEnrolled: 'Error Domain=com.apple.LocalAuthentication Code=-5 "Passcode not set." UserInfo={NSDebugDescription=Passcode not set., NSLocalizedDescription=Passcode is not set.}', biometricNotEnrollIOS: 'Error Domain=com.apple.LocalAuthentication Code=-7 "No identities are enrolled." UserInfo={NSDebugDescription=No identities are enrolled., NSLocalizedDescription=Biometry is not enrolled.}', biometricDeviceLockOut: 'Error Domain=com.apple.LocalAuthentication Code=-8 "Biometry is locked out." UserInfo={NSDebugDescription=Biometry is locked out., NSLocalizedDescription=Biometry is locked out.}', }; export const BiometryTypes = { TouchID, FaceID, Biometrics, }; export module ReactNativeBiometricsLegacy { /** * Returns promise that resolves to an object with object.biometryType = Biometrics | TouchID | FaceID * @returns {Promise<Object>} Promise that resolves to an object with details about biometrics available */ export function isSensorAvailable(): Promise<IsSensorAvailableResult> { return new ReactNativeBiometrics().isSensorAvailable(); } /** * Creates a public private key pair,returns promise that resolves to * an object with object.publicKey, which is the public key of the newly generated key pair * @returns {Promise<Object>} Promise that resolves to object with details about the newly generated public key */ export function createKeys(): Promise<CreateKeysResult> { return new ReactNativeBiometrics().createKeys(); } /** * Returns promise that resolves to an object with object.keysExists = true | false * indicating if the keys were found to exist or not * @returns {Promise<Object>} Promise that resolves to object with details about the existence of keys */ export function biometricKeysExist(): Promise<BiometricKeysExistResult> { return new ReactNativeBiometrics().biometricKeysExist(); } /** * Returns promise that resolves to an object with true | false * indicating if the keys were properly deleted * @returns {Promise<Object>} Promise that resolves to an object with details about the deletion */ export function deleteKeys(): Promise<DeleteKeysResult> { return new ReactNativeBiometrics().deleteKeys(); } /** * Prompts user with biometrics dialog using the passed in prompt message and * returns promise that resolves to an object with object.signature, * which is cryptographic signature of the payload * @param {Object} createSignatureOptions * @param {string} createSignatureOptions.promptMessage * @param {string} createSignatureOptions.payload * @returns {Promise<Object>} Promise that resolves to an object cryptographic signature details */ export function createSignature( createSignatureOptions: CreateSignatureOptions ): Promise<CreateSignatureResult> { return new ReactNativeBiometrics().createSignature(createSignatureOptions); } /** * Prompts user with biometrics dialog using the passed in prompt message and * returns promise that resolves to an object with object.success = true if the user passes, * object.success = false if the user cancels, and rejects if anything fails * @param {Object} simplePromptOptions * @param {string} simplePromptOptions.promptMessage * @param {string} simplePromptOptions.fallbackPromptMessage * @returns {Promise<Object>} Promise that resolves an object with details about the biometrics result */ export function simplePrompt( simplePromptOptions: SimplePromptOptions ): Promise<SimplePromptResult> { return new ReactNativeBiometrics().simplePrompt(simplePromptOptions); } } export default class ReactNativeBiometrics { allowDeviceCredentials = false; /** * @param {Object} rnBiometricsOptions * @param {boolean} rnBiometricsOptions.allowDeviceCredentials */ constructor(rnBiometricsOptions?: RNBiometricsOptions) { const allowDeviceCredentials = rnBiometricsOptions?.allowDeviceCredentials ?? false; this.allowDeviceCredentials = allowDeviceCredentials; } /** * Returns promise that resolves to an object with object.biometryType = Biometrics | TouchID | FaceID * @returns {Promise<Object>} Promise that resolves to an object with details about biometrics available */ isSensorAvailable(): Promise<IsSensorAvailableResult> { return bridge.isSensorAvailable({ allowDeviceCredentials: this.allowDeviceCredentials, }); } /** * Creates a public private key pair,returns promise that resolves to * an object with object.publicKey, which is the public key of the newly generated key pair * @returns {Promise<Object>} Promise that resolves to object with details about the newly generated public key */ createKeys(): Promise<CreateKeysResult> { return bridge.createKeys({ allowDeviceCredentials: this.allowDeviceCredentials, }); } /** * Returns promise that resolves to an object with object.keysExists = true | false * indicating if the keys were found to exist or not * @returns {Promise<Object>} Promise that resolves to object with details aobut the existence of keys */ biometricKeysExist(): Promise<BiometricKeysExistResult> { return bridge.biometricKeysExist(); } /** * Returns promise that resolves to an object with true | false * indicating if the keys were properly deleted * @returns {Promise<Object>} Promise that resolves to an object with details about the deletion */ deleteKeys(): Promise<DeleteKeysResult> { return bridge.deleteKeys(); } /** * Prompts user with biometrics dialog using the passed in prompt message and * returns promise that resolves to an object with object.signature, * which is cryptographic signature of the payload * @param {Object} createSignatureOptions * @param {string} createSignatureOptions.promptMessage * @param {string} createSignatureOptions.payload * @returns {Promise<Object>} Promise that resolves to an object cryptographic signature details */ createSignature( createSignatureOptions: CreateSignatureOptions ): Promise<CreateSignatureResult> { createSignatureOptions.cancelButtonText = createSignatureOptions.cancelButtonText ?? "Cancel"; return bridge.createSignature({ allowDeviceCredentials: this.allowDeviceCredentials, ...createSignatureOptions, }); } /** * Prompts user with biometrics dialog using the passed in prompt message and * returns promise that resolves to an object with object.success = true if the user passes, * object.success = false if the user cancels, and rejects if anything fails * @param {Object} simplePromptOptions * @param {string} simplePromptOptions.promptMessage * @param {string} simplePromptOptions.fallbackPromptMessage * @returns {Promise<Object>} Promise that resolves an object with details about the biometrics result */ simplePrompt( simplePromptOptions: SimplePromptOptions ): Promise<SimplePromptResult> { simplePromptOptions.cancelButtonText = simplePromptOptions.cancelButtonText ?? "Cancel"; simplePromptOptions.fallbackPromptMessage = simplePromptOptions.fallbackPromptMessage ?? "Use Passcode"; return bridge.simplePrompt({ allowDeviceCredentials: this.allowDeviceCredentials, ...simplePromptOptions, }); } async generateKey() { const response = await this.createKeys(); return response.publicKey; } async _addDeviceAuthenticationUtil( authenticationOptions: AuthenticationOptions ) { const response = await this.simplePrompt({ promptMessage: authenticationOptions.promptMessage, fallbackPromptMessage: authenticationOptions.fallbackPromptMessage, cancelButtonText: authenticationOptions.cancelButtonText, }); if (response.success) { return authenticationOptions.successCallback({ publicKey: authenticationOptions.encryption ? this.generateKey() : "", }); } else if (response.error) { return authenticationOptions.errorCallback({ error: response.error, }); } } addDeviceAuthentication( authenticationOptions: AuthenticationOptions ): Promise<AuthenticationResult> { return this._addDeviceAuthenticationUtil(authenticationOptions); } }