From 9529c1621520750a8bee98e2058147cd399e655b Mon Sep 17 00:00:00 2001 From: Gokul Kulkarni Date: Tue, 5 Sep 2023 01:08:31 +0530 Subject: [PATCH] Added fallback mechanism for android --- KeychainExample/App.js | 23 ++++++++++++++++++- .../com/oblador/keychain/KeychainModule.java | 14 ++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/KeychainExample/App.js b/KeychainExample/App.js index f61c5ad6..5d1acae0 100644 --- a/KeychainExample/App.js +++ b/KeychainExample/App.js @@ -13,7 +13,7 @@ import SegmentedControlTab from 'react-native-segmented-control-tab'; import * as Keychain from 'react-native-keychain'; const ACCESS_CONTROL_OPTIONS = ['None', 'Passcode', 'Password']; -const ACCESS_CONTROL_OPTIONS_ANDROID = ['None']; +const ACCESS_CONTROL_OPTIONS_ANDROID = ['None', 'Fallback']; const ACCESS_CONTROL_MAP = [ null, Keychain.ACCESS_CONTROL.DEVICE_PASSCODE, @@ -22,6 +22,7 @@ const ACCESS_CONTROL_MAP = [ ]; const ACCESS_CONTROL_MAP_ANDROID = [ null, + Keychain.ACCESS_CONTROL.BIOMETRY_ANY_OR_DEVICE_PASSCODE, Keychain.ACCESS_CONTROL.BIOMETRY_CURRENT_SET, ]; const SECURITY_LEVEL_OPTIONS = ['Any', 'Software', 'Hardware']; @@ -39,6 +40,13 @@ const SECURITY_STORAGE_MAP = [ Keychain.STORAGE_TYPE.RSA, ]; +const ACCESS_CTRL_TO_AUTH_TYPE = { + [Keychain.ACCESS_CONTROL.BIOMETRY_ANY]: + Keychain.AUTHENTICATION_TYPE.BIOMETRICS, + [Keychain.ACCESS_CONTROL.BIOMETRY_ANY_OR_DEVICE_PASSCODE]: + Keychain.AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS, +}; + export default class KeychainExample extends Component { state = { username: '', @@ -94,6 +102,18 @@ export default class KeychainExample extends Component { cancel: 'Cancel', }, }; + if (this.state.accessControl) { + options.authenticationType = + ACCESS_CTRL_TO_AUTH_TYPE[this.state.accessControl]; + options.accessControl = this.state.accessControl; + } + if ( + Platform.OS === 'android' && + options.authenticationType === + Keychain.AUTHENTICATION_TYPE.DEVICE_PASSCODE_OR_BIOMETRICS + ) { + options.authenticationPrompt.cancel = ''; + } const credentials = await Keychain.getGenericPassword(options); if (credentials) { this.setState({ ...credentials, status: 'Credentials loaded!' }); @@ -340,6 +360,7 @@ const styles = StyleSheet.create({ fontWeight: '500', fontSize: 15, marginBottom: 5, + color: 'black', }, input: { color: '#000', diff --git a/android/src/main/java/com/oblador/keychain/KeychainModule.java b/android/src/main/java/com/oblador/keychain/KeychainModule.java index 9413000c..49de09e6 100644 --- a/android/src/main/java/com/oblador/keychain/KeychainModule.java +++ b/android/src/main/java/com/oblador/keychain/KeychainModule.java @@ -52,6 +52,7 @@ public class KeychainModule extends ReactContextBaseJavaModule { public static final String IRIS_SUPPORTED_NAME = "Iris"; public static final String EMPTY_STRING = ""; public static final String WARMING_UP_ALIAS = "warmingUp"; + public static final String AUTHENTICATION_TYPE = "authenticationType"; private static final String LOG_TAG = KeychainModule.class.getSimpleName(); @@ -74,6 +75,13 @@ public class KeychainModule extends ReactContextBaseJavaModule { String BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE = "BiometryCurrentSetOrDevicePasscode"; } + @StringDef({AuthenticateType.BIOMETRICS + , AuthenticateType.DEVICE_PASSCODE_OR_BIOMETRICS}) + @interface AuthenticateType { + String DEVICE_PASSCODE_OR_BIOMETRICS = "AuthenticationWithBiometricsDevicePasscode"; + String BIOMETRICS = "AuthenticationWithBiometrics"; + } + @interface AuthPromptOptions { String TITLE = "title"; String SUBTITLE = "subtitle"; @@ -618,7 +626,11 @@ private static PromptInfo getPromptInfo(@Nullable final ReadableMap options) { } /* PromptInfo is only used in Biometric-enabled RSA storage and can only be unlocked by a strong biometric */ - promptInfoBuilder.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); + int allowedAuthenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && options.hasKey(AUTHENTICATION_TYPE) && options.getString(AUTHENTICATION_TYPE).equals(AuthenticateType.DEVICE_PASSCODE_OR_BIOMETRICS)) { + allowedAuthenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL; + } + promptInfoBuilder.setAllowedAuthenticators(allowedAuthenticators); /* Bypass confirmation to avoid KeyStore unlock timeout being exceeded when using passive biometrics */ promptInfoBuilder.setConfirmationRequired(false);