From 40455488808968a1bcf0004b011500204f27c5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janda=C4=8Dka=20Mari=C3=A1n?= Date: Fri, 26 Jan 2024 13:11:05 +0100 Subject: [PATCH 1/3] added accessGroup option for ios devices --- index.ts | 263 +++++++++++++++++++----------------- ios/ReactNativeBiometrics.m | 10 +- package.json | 18 +-- 3 files changed, 160 insertions(+), 131 deletions(-) diff --git a/index.ts b/index.ts index 32528b4..5dcb152 100644 --- a/index.ts +++ b/index.ts @@ -1,75 +1,79 @@ -import { NativeModules } from 'react-native' +import { NativeModules } from "react-native"; -const { ReactNativeBiometrics: bridge } = NativeModules +const { ReactNativeBiometrics: bridge } = NativeModules; /** * Type alias for possible biometry types */ -export type BiometryType = 'TouchID' | 'FaceID' | 'Biometrics' +export type BiometryType = "TouchID" | "FaceID" | "Biometrics"; interface RNBiometricsOptions { - allowDeviceCredentials?: boolean + allowDeviceCredentials?: boolean; } interface IsSensorAvailableResult { - available: boolean - biometryType?: BiometryType - error?: string + available: boolean; + biometryType?: BiometryType; + error?: string; } interface CreateKeysResult { - publicKey: string + publicKey: string; } interface BiometricKeysExistResult { - keysExist: boolean + keysExist: boolean; } interface DeleteKeysResult { - keysDeleted: boolean + keysDeleted: boolean; } interface CreateSignatureOptions { - promptMessage: string - payload: string - cancelButtonText?: string + promptMessage: string; + payload: string; + cancelButtonText?: string; } interface CreateSignatureResult { - success: boolean - signature?: string - error?: string + success: boolean; + signature?: string; + error?: string; } interface SimplePromptOptions { - promptMessage: string - fallbackPromptMessage?: string - cancelButtonText?: string + promptMessage: string; + fallbackPromptMessage?: string; + cancelButtonText?: string; } interface SimplePromptResult { - success: boolean - error?: string + success: boolean; + error?: string; +} + +interface Options { + accessGroup?: string; } /** * Enum for touch id sensor type */ -export const TouchID = 'TouchID' +export const TouchID = "TouchID"; /** * Enum for face id sensor type */ -export const FaceID = 'FaceID' +export const FaceID = "FaceID"; /** * Enum for generic biometrics (this is the only value available on android) */ -export const Biometrics = 'Biometrics' +export const Biometrics = "Biometrics"; export const BiometryTypes = { TouchID, FaceID, - Biometrics -} + Biometrics, +}; export module ReactNativeBiometricsLegacy { /** @@ -77,7 +81,7 @@ export module ReactNativeBiometricsLegacy { * @returns {Promise} Promise that resolves to an object with details about biometrics available */ export function isSensorAvailable(): Promise { - return new ReactNativeBiometrics().isSensorAvailable() + return new ReactNativeBiometrics().isSensorAvailable(); } /** @@ -85,8 +89,11 @@ export module ReactNativeBiometricsLegacy { * an object with object.publicKey, which is the public key of the newly generated key pair * @returns {Promise} Promise that resolves to object with details about the newly generated public key */ - export function createKeys(): Promise { - return new ReactNativeBiometrics().createKeys() + export function createKeys( + createKeyOptions?: Options + ): Promise { + const keyOptions = createKeyOptions || {}; + return new ReactNativeBiometrics().createKeys(keyOptions); } /** @@ -95,7 +102,7 @@ export module ReactNativeBiometricsLegacy { * @returns {Promise} Promise that resolves to object with details about the existence of keys */ export function biometricKeysExist(): Promise { - return new ReactNativeBiometrics().biometricKeysExist() + return new ReactNativeBiometrics().biometricKeysExist(); } /** @@ -104,7 +111,7 @@ export module ReactNativeBiometricsLegacy { * @returns {Promise} Promise that resolves to an object with details about the deletion */ export function deleteKeys(): Promise { - return new ReactNativeBiometrics().deleteKeys() + return new ReactNativeBiometrics().deleteKeys(); } /** @@ -116,8 +123,10 @@ export module ReactNativeBiometricsLegacy { * @param {string} createSignatureOptions.payload * @returns {Promise} Promise that resolves to an object cryptographic signature details */ - export function createSignature(createSignatureOptions: CreateSignatureOptions): Promise { - return new ReactNativeBiometrics().createSignature(createSignatureOptions) + export function createSignature( + createSignatureOptions: CreateSignatureOptions + ): Promise { + return new ReactNativeBiometrics().createSignature(createSignatureOptions); } /** @@ -129,96 +138,108 @@ export module ReactNativeBiometricsLegacy { * @param {string} simplePromptOptions.fallbackPromptMessage * @returns {Promise} Promise that resolves an object with details about the biometrics result */ - export function simplePrompt(simplePromptOptions: SimplePromptOptions): Promise { - return new ReactNativeBiometrics().simplePrompt(simplePromptOptions) + export function simplePrompt( + simplePromptOptions: SimplePromptOptions + ): Promise { + 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} Promise that resolves to an object with details about biometrics available - */ - isSensorAvailable(): Promise { - 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} Promise that resolves to object with details about the newly generated public key - */ - createKeys(): Promise { - 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} Promise that resolves to object with details aobut the existence of keys - */ - biometricKeysExist(): Promise { - return bridge.biometricKeysExist() - } - - /** - * Returns promise that resolves to an object with true | false - * indicating if the keys were properly deleted - * @returns {Promise} Promise that resolves to an object with details about the deletion - */ - deleteKeys(): Promise { - 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} Promise that resolves to an object cryptographic signature details - */ - createSignature(createSignatureOptions: CreateSignatureOptions): Promise { - 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} Promise that resolves an object with details about the biometrics result - */ - simplePrompt(simplePromptOptions: SimplePromptOptions): Promise { - simplePromptOptions.cancelButtonText = simplePromptOptions.cancelButtonText ?? 'Cancel' - simplePromptOptions.fallbackPromptMessage = simplePromptOptions.fallbackPromptMessage ?? 'Use Passcode' - - return bridge.simplePrompt({ - allowDeviceCredentials: this.allowDeviceCredentials, - ...simplePromptOptions - }) - } + 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} Promise that resolves to an object with details about biometrics available + */ + isSensorAvailable(): Promise { + 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} Promise that resolves to object with details about the newly generated public key + */ + createKeys(createKeyOptions?: Options): Promise { + const keyOptions = createKeyOptions || {}; + return bridge.createKeys({ + allowDeviceCredentials: this.allowDeviceCredentials, + ...keyOptions, + }); + } + + /** + * Returns promise that resolves to an object with object.keysExists = true | false + * indicating if the keys were found to exist or not + * @returns {Promise} Promise that resolves to object with details aobut the existence of keys + */ + biometricKeysExist(): Promise { + return bridge.biometricKeysExist(); } + + /** + * Returns promise that resolves to an object with true | false + * indicating if the keys were properly deleted + * @returns {Promise} Promise that resolves to an object with details about the deletion + */ + deleteKeys(): Promise { + 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} Promise that resolves to an object cryptographic signature details + */ + createSignature( + createSignatureOptions: CreateSignatureOptions + ): Promise { + 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} Promise that resolves an object with details about the biometrics result + */ + simplePrompt( + simplePromptOptions: SimplePromptOptions + ): Promise { + simplePromptOptions.cancelButtonText = + simplePromptOptions.cancelButtonText ?? "Cancel"; + simplePromptOptions.fallbackPromptMessage = + simplePromptOptions.fallbackPromptMessage ?? "Use Passcode"; + + return bridge.simplePrompt({ + allowDeviceCredentials: this.allowDeviceCredentials, + ...simplePromptOptions, + }); + } +} diff --git a/ios/ReactNativeBiometrics.m b/ios/ReactNativeBiometrics.m index 03ec388..d78c63b 100644 --- a/ios/ReactNativeBiometrics.m +++ b/ios/ReactNativeBiometrics.m @@ -77,9 +77,17 @@ @implementation ReactNativeBiometrics } }; + NSMutableDictionary *keyAttributesWithOptions = keyAttributes.mutableCopy; + + NSString *accessGroup = [RCTConvert NSString:params[@"accessGroup"]]; + + if (accessGroup != nil) { + mAttributes[(id)kSecAttrAccessGroup] = accessGroup; + } + [self deleteBiometricKey]; NSError *gen_error = nil; - id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((__bridge CFDictionaryRef)keyAttributes, (void *)&gen_error)); + id privateKey = CFBridgingRelease(SecKeyCreateRandomKey((__bridge CFDictionaryRef)keyAttributesWithOptions, (void *)&gen_error)); if(privateKey != nil) { id publicKey = CFBridgingRelease(SecKeyCopyPublicKey((SecKeyRef)privateKey)); diff --git a/package.json b/package.json index 65cdb71..a10ba6d 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "react-native-biometrics", - "version": "3.0.1", - "summary": "A React Native library for biometrics", - "description": "React Native biometric functionality for signing and encryption", + "name": "@marianJ97/react-native-biometrics", + "version": "1.0.0", + "summary": "A fork of React Native library for biometrics", + "description": "A forked repository that comes from SelfLender/react-native-biometrics and includes React Native biometric functionality for signing and encryption that allows additional options when generating keys (more added later)", "main": "build/cjs/index.js", "module": "build/esm/index.js", "types": "build/esm/index.d.ts", @@ -24,23 +24,23 @@ "touch-id", "face-id" ], - "homepage": "https://github.com/SelfLender/react-native-biometrics", + "homepage": "https://github.com/marianJ97/react-native-biometrics", "contributors": [], "repository": { "type": "git", - "url": "git+https://github.com/SelfLender/react-native-biometrics.git" + "url": "git+https://github.com/marianJ97/react-native-biometrics.git" }, "private": false, "author": { - "name": "Brandon Hines", - "url": "https://github.com/NappyPirate" + "name": "Marian Jandacka", + "url": "https://https://github.com/marianJ97" }, "license": "MIT", "peerDependencies": { "react-native": ">=0.60.0" }, "bugs": { - "url": "https://github.com/SelfLender/react-native-biometrics/issues" + "url": "https://github.com/marianJ97/react-native-biometrics/issues" }, "devDependencies": { "typescript": "^3.7.2" From d41a5458d92c227a0c47ade844459ef1677535fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janda=C4=8Dka=20Mari=C3=A1n?= Date: Mon, 29 Jan 2024 14:05:02 +0100 Subject: [PATCH 2/3] revert package changes --- package.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index a10ba6d..65cdb71 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "@marianJ97/react-native-biometrics", - "version": "1.0.0", - "summary": "A fork of React Native library for biometrics", - "description": "A forked repository that comes from SelfLender/react-native-biometrics and includes React Native biometric functionality for signing and encryption that allows additional options when generating keys (more added later)", + "name": "react-native-biometrics", + "version": "3.0.1", + "summary": "A React Native library for biometrics", + "description": "React Native biometric functionality for signing and encryption", "main": "build/cjs/index.js", "module": "build/esm/index.js", "types": "build/esm/index.d.ts", @@ -24,23 +24,23 @@ "touch-id", "face-id" ], - "homepage": "https://github.com/marianJ97/react-native-biometrics", + "homepage": "https://github.com/SelfLender/react-native-biometrics", "contributors": [], "repository": { "type": "git", - "url": "git+https://github.com/marianJ97/react-native-biometrics.git" + "url": "git+https://github.com/SelfLender/react-native-biometrics.git" }, "private": false, "author": { - "name": "Marian Jandacka", - "url": "https://https://github.com/marianJ97" + "name": "Brandon Hines", + "url": "https://github.com/NappyPirate" }, "license": "MIT", "peerDependencies": { "react-native": ">=0.60.0" }, "bugs": { - "url": "https://github.com/marianJ97/react-native-biometrics/issues" + "url": "https://github.com/SelfLender/react-native-biometrics/issues" }, "devDependencies": { "typescript": "^3.7.2" From 77bd7ea423f5b39a5120e6b97aa97e008ac91147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janda=C4=8Dka=20Mari=C3=A1n?= Date: Mon, 29 Jan 2024 14:06:27 +0100 Subject: [PATCH 3/3] fixed variable name --- ios/ReactNativeBiometrics.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/ReactNativeBiometrics.m b/ios/ReactNativeBiometrics.m index d78c63b..d100190 100644 --- a/ios/ReactNativeBiometrics.m +++ b/ios/ReactNativeBiometrics.m @@ -82,7 +82,7 @@ @implementation ReactNativeBiometrics NSString *accessGroup = [RCTConvert NSString:params[@"accessGroup"]]; if (accessGroup != nil) { - mAttributes[(id)kSecAttrAccessGroup] = accessGroup; + keyAttributesWithOptions[(id)kSecAttrAccessGroup] = accessGroup; } [self deleteBiometricKey];