diff --git a/README.md b/README.md index 4ef388f..f99b79b 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,7 @@ Get what type of hardware biometry support the device has. Resolves to a `Keycha |-----|-------------| |**`TOUCH_ID`**|Device supports authentication with Touch ID.| |**`FACE_ID`**|Device supports authentication with Face ID.| +|**`FINGERPRINT`**|Device supports authentication with Android Fingerprint.| ## Manual Installation diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 19a839b..ddbe506 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - + diff --git a/android/src/main/java/com/oblador/keychain/DeviceAvailability.java b/android/src/main/java/com/oblador/keychain/DeviceAvailability.java new file mode 100644 index 0000000..75afa6d --- /dev/null +++ b/android/src/main/java/com/oblador/keychain/DeviceAvailability.java @@ -0,0 +1,23 @@ +package com.oblador.keychain; + +import android.os.Build; +import android.content.Context; +import android.app.KeyguardManager; +import android.hardware.fingerprint.FingerprintManager; + +public class DeviceAvailability { + public static boolean isFingerprintAuthAvailable(Context context) { + FingerprintManager fingerprintManager = + (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE); + + return android.os.Build.VERSION.SDK_INT >= 23 && + fingerprintManager.isHardwareDetected() && + fingerprintManager.hasEnrolledFingerprints(); + } + + public static boolean isSecure(Context context) { + KeyguardManager keyguardManager = + (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); + return android.os.Build.VERSION.SDK_INT >= 23 && keyguardManager.isDeviceSecure(); + } +} diff --git a/android/src/main/java/com/oblador/keychain/KeychainModule.java b/android/src/main/java/com/oblador/keychain/KeychainModule.java index edbac50..45ee5a8 100644 --- a/android/src/main/java/com/oblador/keychain/KeychainModule.java +++ b/android/src/main/java/com/oblador/keychain/KeychainModule.java @@ -20,6 +20,7 @@ import com.oblador.keychain.cipherStorage.CipherStorageKeystoreAESCBC; import com.oblador.keychain.exceptions.CryptoFailedException; import com.oblador.keychain.exceptions.EmptyParameterException; import com.oblador.keychain.exceptions.KeyStoreAccessException; +import com.oblador.keychain.DeviceAvailability; import java.util.HashMap; import java.util.Map; @@ -29,7 +30,9 @@ public class KeychainModule extends ReactContextBaseJavaModule { public static final String E_EMPTY_PARAMETERS = "E_EMPTY_PARAMETERS"; public static final String E_CRYPTO_FAILED = "E_CRYPTO_FAILED"; public static final String E_KEYSTORE_ACCESS_ERROR = "E_KEYSTORE_ACCESS_ERROR"; + public static final String E_SUPPORTED_BIOMETRY_ERROR = "E_SUPPORTED_BIOMETRY_ERROR"; public static final String KEYCHAIN_MODULE = "RNKeychainManager"; + public static final String FINGERPRINT_SUPPORTED_NAME = "Fingerprint"; public static final String EMPTY_STRING = ""; private final Map cipherStorageMap = new HashMap<>(); @@ -161,6 +164,21 @@ public class KeychainModule extends ReactContextBaseJavaModule { resetGenericPasswordForOptions(server, promise); } + @ReactMethod + public void getSupportedBiometryType(Promise promise) { + try { + boolean fingerprintAuthAvailable = isFingerprintAuthAvailable(); + if (fingerprintAuthAvailable) { + promise.resolve(FINGERPRINT_SUPPORTED_NAME); + } else { + promise.resolve(null); + } + } catch (Exception e) { + Log.e(KEYCHAIN_MODULE, e.getMessage()); + promise.reject(E_SUPPORTED_BIOMETRY_ERROR, e); + } + } + // The "Current" CipherStorage is the cipherStorage with the highest API level that is lower than or equal to the current API level private CipherStorage getCipherStorageForCurrentAPILevel() throws CryptoFailedException { int currentAPILevel = Build.VERSION.SDK_INT; @@ -184,6 +202,10 @@ public class KeychainModule extends ReactContextBaseJavaModule { return cipherStorageMap.get(cipherStorageName); } + private boolean isFingerprintAuthAvailable() { + return DeviceAvailability.isFingerprintAuthAvailable(getCurrentActivity()); + } + @NonNull private String getDefaultServiceIfNull(String service) { return service == null ? EMPTY_STRING : service; diff --git a/index.js b/index.js index 18f481b..cadec3d 100644 --- a/index.js +++ b/index.js @@ -30,6 +30,7 @@ export const AUTHENTICATION_TYPE = { export const BIOMETRY_TYPE = { TOUCH_ID: 'TouchID', FACE_ID: 'FaceID', + FINGERPRINT: 'Fingerprint', }; type SecAccessible =