diff --git a/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.h b/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.h index 4a1234f..f3e2308 100644 --- a/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.h +++ b/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.h @@ -10,5 +10,6 @@ #import @interface RNKeychainManager : NSObject - +-(OSStatus)deleteCredentialsForServer:(NSString *)server; +-(NSArray*)getAllServersForInternetPasswords; @end diff --git a/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m b/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m index 1e7021c..6990ae4 100644 --- a/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m +++ b/node_modules/react-native-keychain/RNKeychainManager/RNKeychainManager.m @@ -271,6 +271,36 @@ SecAccessControlCreateFlags accessControlValue(NSDictionary *options) return SecItemDelete((__bridge CFDictionaryRef) query); } +-(NSArray*)getAllServersForInternetPasswords +{ + NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys: + (__bridge id)kCFBooleanTrue, (__bridge id)kSecReturnAttributes, + (__bridge id)kSecMatchLimitAll, (__bridge id)kSecMatchLimit, + nil]; + NSMutableArray *servers = [NSMutableArray new]; + + [query setObject:(__bridge id)kSecClassInternetPassword forKey:(__bridge id)kSecClass]; + NSArray *result = nil; + CFTypeRef resultRef = NULL; + OSStatus osStatus = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&resultRef); + if (osStatus != noErr && osStatus != errSecItemNotFound) { + NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:osStatus userInfo:nil]; + @throw error; + } else if (osStatus != errSecItemNotFound) { + result = (__bridge NSArray*)(resultRef); + if (result != NULL) { + for (id entry in result) { + NSString *serverData = [entry objectForKey:(__bridge NSString *)kSecAttrServer]; + if (serverData != NULL) { + [servers addObject:serverData]; + } + } + } + } + + return servers; +} + -(NSArray*)getAllServicesForSecurityClasses:(NSArray *)secItemClasses { NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys: @@ -598,4 +628,14 @@ RCT_EXPORT_METHOD(getAllGenericPasswordServices:(RCTPromiseResolveBlock)resolve } } +RCT_EXPORT_METHOD(getAllInternetPasswordServers:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + @try { + NSArray *servers = [self getAllServersForInternetPasswords]; + return resolve(servers); + } @catch (NSError *nsError) { + return rejectWithError(reject, nsError); + } +} + @end diff --git a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java index 6ca68cb..dacb1ed 100644 --- a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java +++ b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java @@ -1,6 +1,7 @@ package com.oblador.keychain; import android.os.Build; +import android.os.Bundle; import android.text.TextUtils; import android.util.Log; @@ -129,6 +130,7 @@ public class KeychainModule extends ReactContextBaseJavaModule { //region Members /** Name-to-instance lookup map. */ private final Map cipherStorageMap = new HashMap<>(); + private final Map cachedCredentialsMap = new HashMap<>(); /** Shared preferences storage. */ private final PrefsStorage prefsStorage; //endregion @@ -140,13 +142,7 @@ public class KeychainModule extends ReactContextBaseJavaModule { super(reactContext); prefsStorage = new PrefsStorage(reactContext); - addCipherStorageToMap(new CipherStorageFacebookConceal(reactContext)); addCipherStorageToMap(new CipherStorageKeystoreAesCbc()); - - // we have a references to newer api that will fail load of app classes in old androids OS - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - addCipherStorageToMap(new CipherStorageKeystoreRsaEcb()); - } } /** Allow initialization in chain. */ @@ -278,6 +274,11 @@ public class KeychainModule extends ReactContextBaseJavaModule { @Nullable final ReadableMap options, @NonNull final Promise promise) { try { + Bundle cached = cachedCredentialsMap.get(alias); + if (cached != null) { + promise.resolve(Arguments.fromBundle(cached)); + return; + } final ResultSet resultSet = prefsStorage.getEncryptedEntry(alias); if (resultSet == null) { @@ -310,6 +311,7 @@ public class KeychainModule extends ReactContextBaseJavaModule { credentials.putString(Maps.USERNAME, decryptionResult.username); credentials.putString(Maps.PASSWORD, decryptionResult.password); credentials.putString(Maps.STORAGE, cipher.getCipherStorageName()); + cachedCredentialsMap.put(alias, Arguments.toBundle(credentials)); promise.resolve(credentials); } catch (KeyStoreAccessException e) { @@ -382,6 +384,7 @@ public class KeychainModule extends ReactContextBaseJavaModule { } // And then we remove the entry in the shared preferences prefsStorage.removeEntry(alias); + cachedCredentialsMap.remove(alias); promise.resolve(true); } catch (KeyStoreAccessException e) { diff --git a/node_modules/react-native-keychain/index.js b/node_modules/react-native-keychain/index.js index 75c0d5c..e6c44d8 100644 --- a/node_modules/react-native-keychain/index.js +++ b/node_modules/react-native-keychain/index.js @@ -352,6 +352,21 @@ export function canImplyAuthentication(options?: Options): Promise { return RNKeychainManager.canCheckAuthentication(options); } +/** ++ * Gets all `kSecAttrServer` values used in internet credentials for iOS. ++ * @return {Promise} Resolves to an array of strings ++ */ +export async function getAllInternetPasswordServers(): Promise { + if (Platform.OS !== 'ios') { + return Promise.reject( + new Error( + `getAllInternetPasswordServers() is not supported on ${Platform.OS}` + ) + ); + } + return RNKeychainManager.getAllInternetPasswordServers(); +} + //* ANDROID ONLY */ /** diff --git a/node_modules/react-native-keychain/typings/react-native-keychain.d.ts b/node_modules/react-native-keychain/typings/react-native-keychain.d.ts index af2eb56..038047b 100644 --- a/node_modules/react-native-keychain/typings/react-native-keychain.d.ts +++ b/node_modules/react-native-keychain/typings/react-native-keychain.d.ts @@ -97,6 +97,8 @@ declare module 'react-native-keychain' { function getAllGenericPasswordServices(): Promise; + function getAllInternetPasswordServers(): Promise; + function hasInternetCredentials(server: string): Promise; function setInternetCredentials(