Search code examples
ioserror-handlingkeychainerror-code

Keychain access in iOS: "Keychain failed to store the value with code: -50"


I don't find the information regarding such error code when calling SecItemAdd, what could be causing it?

Thanks in advance

EDIT: This is the function where I get the error:

+ (BOOL)storeWithKey:(NSString *)keyStr withValueStr:(NSString *)valueStr
{
   if ((keyStr != nil) && (![keyStr isEqualToString:@""]) &&
       (valueStr != nil) && (![valueStr isEqualToString:@""])) {

       NSData *valueData = [valueStr dataUsingEncoding:NSUTF8StringEncoding];
       NSString *service = [[NSBundle mainBundle] bundleIdentifier];

       NSDictionary *secItem = @{(__bridge id)kSecClass : (__bridge id)kSecClassInternetPassword,
                              (__bridge id)kSecAttrService : service,
                              (__bridge id)kSecAttrAccount : keyStr,
                              (__bridge id)kSecValueData : valueData};

       CFTypeRef result = NULL;

       // Store value and get the result code
       OSStatus status = SecItemAdd((__bridge CFDictionaryRef)secItem, &result);

       NSLog(@"'writeToKeychain'. %@", [self getErrorMessage:status]);

       return [self checkIfInKeychain:status];
   }
   else {
       return NO;
   }
}

Solution

  • -50 means One or more parameters passed to a function were not valid. You're wrong combination of parameters.

    If you use kSecAttrService and kSecAttrAccount, kSecClass should be kSecClassGenericPassword.

    NSDictionary *secItem = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
                              (__bridge id)kSecAttrService : service,
                              (__bridge id)kSecAttrAccount : keyStr,
                              (__bridge id)kSecValueData : valueData};
    

    If you use kSecClassInternetPassword as kSecClass, you should use kSecAttrServer and kSecAttrPort (If needed) instead kSecAttrService.

    NSDictionary *secItem = @{(__bridge id)kSecClass : (__bridge id)kSecClassInternetPassword,
                              (__bridge id)kSecAttrServer : @"example.com",
                              (__bridge id)kSecAttrPort : @(80), // Optional
                              (__bridge id)kSecAttrAccount : keyStr,
                              (__bridge id)kSecValueData : valueData};