diff --git a/RNKeychainManager/RNKeychainManager.m b/RNKeychainManager/RNKeychainManager.m index 1e7021c0..ca107902 100644 --- a/RNKeychainManager/RNKeychainManager.m +++ b/RNKeychainManager/RNKeychainManager.m @@ -136,6 +136,14 @@ CFStringRef accessibleValue(NSDictionary *options) return nil; } +NSString *applicationPasswordValue(NSDictionary *options) +{ + if (options && options[@"applicationPassword"] != nil) { + return options[@"applicationPassword"]; + } + return nil; +} + #pragma mark - Proposed functionality - Helpers #define kAuthenticationType @"authenticationType" @@ -350,12 +358,21 @@ - (OSStatus)deleteCredentialsForServer:(NSString *)server rejecter:(RCTPromiseRejectBlock)reject) { NSString *service = serviceValue(options); - NSDictionary *attributes = attributes = @{ - (__bridge NSString *)kSecClass: (__bridge id)(kSecClassGenericPassword), - (__bridge NSString *)kSecAttrService: service, - (__bridge NSString *)kSecAttrAccount: username, - (__bridge NSString *)kSecValueData: [password dataUsingEncoding:NSUTF8StringEncoding] - }; + NSString *applicationPassword = applicationPasswordValue(options); + + NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary: @{ + (__bridge NSString *)kSecClass: (__bridge id)(kSecClassGenericPassword), + (__bridge NSString *)kSecAttrService: service, + (__bridge NSString *)kSecAttrAccount: username, + (__bridge NSString *)kSecValueData: [password dataUsingEncoding:NSUTF8StringEncoding] + }]; + + if (applicationPassword != nil) { + LAContext *context = [LAContext new]; + [context setCredential: [applicationPassword dataUsingEncoding: NSUTF8StringEncoding] type: LACredentialTypeApplicationPassword]; + + attributes[(__bridge NSString *)kSecUseAuthenticationContext] = context; + } [self deletePasswordsForService:service]; @@ -368,15 +385,23 @@ - (OSStatus)deleteCredentialsForServer:(NSString *)server { NSString *service = serviceValue(options); NSString *authenticationPrompt = authenticationPromptValue(options); - - NSDictionary *query = @{ - (__bridge NSString *)kSecClass: (__bridge id)(kSecClassGenericPassword), - (__bridge NSString *)kSecAttrService: service, - (__bridge NSString *)kSecReturnAttributes: (__bridge id)kCFBooleanTrue, - (__bridge NSString *)kSecReturnData: (__bridge id)kCFBooleanTrue, - (__bridge NSString *)kSecMatchLimit: (__bridge NSString *)kSecMatchLimitOne, - (__bridge NSString *)kSecUseOperationPrompt: authenticationPrompt - }; + NSString *applicationPassword = applicationPasswordValue(options); + + NSMutableDictionary *query = [NSMutableDictionary dictionaryWithDictionary: @{ + (__bridge NSString *)kSecClass: (__bridge id)(kSecClassGenericPassword), + (__bridge NSString *)kSecAttrService: service, + (__bridge NSString *)kSecReturnAttributes: (__bridge id)kCFBooleanTrue, + (__bridge NSString *)kSecReturnData: (__bridge id)kCFBooleanTrue, + (__bridge NSString *)kSecMatchLimit: (__bridge NSString *)kSecMatchLimitOne, + (__bridge NSString *)kSecUseOperationPrompt: authenticationPrompt + }]; + + if (applicationPassword != nil) { + LAContext *context = [LAContext new]; + [context setCredential: [applicationPassword dataUsingEncoding: NSUTF8StringEncoding] type: LACredentialTypeApplicationPassword]; + + query[(__bridge NSString *)kSecUseAuthenticationContext] = context; + } // Look up service in the keychain NSDictionary *found = nil; diff --git a/typings/react-native-keychain.d.ts b/typings/react-native-keychain.d.ts index af2eb561..ced8d931 100644 --- a/typings/react-native-keychain.d.ts +++ b/typings/react-native-keychain.d.ts @@ -81,6 +81,7 @@ declare module 'react-native-keychain' { securityLevel?: SECURITY_LEVEL; storage?: STORAGE_TYPE; rules?: SECURITY_RULES; + applicationPassword?: string | undefined; } function setGenericPassword(