14
votes

Apple has provided KeyChainItemWrapper class in their GenericKeyChain sample code. There is an ARC'ed solution here on SO, which I am trying to follow: wrapper to store in the KeyChain on iOS.

The usage of the wrapper is like this:

KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"F11-email-auth" accessGroup:nil];
[keychain setObject:[emailTextfield text] forKey:(__bridge id)(kSecMatchEmailAddressIfPresent)];
[keychain setObject:[passwordTextfield text] forKey:(__bridge id)(kSecClassGenericPassword)];

the line with email text field is accepted. But the second line with the password crashes with the following exception.

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Couldn't add the Keychain Item.'
*** First throw call stack:
(
    0   CoreFoundation                      0x01b445e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x018c78b6 objc_exception_throw + 44
    2   CoreFoundation                      0x01b44448 +[NSException raise:format:arguments:] + 136
    3   Foundation                          0x014a823e -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
    4   Feeltracker                         0x000053b3 -[KeychainItemWrapper writeToKeychain] + 899
    5   Feeltracker                         0x00004700 -[KeychainItemWrapper setObject:forKey:] + 272
    6   Feeltracker                         0x000092d6 -[FTLoginViewController connectToAccount:] + 374
    7   libobjc.A.dylib                     0x018d9874 -

What could be the reason? I wonder if it has anything to do with the constants I am using.

UPDATE:

Thanks to rmaddy's help:

This is the bit that seems to throw the error:

// No previous item found; add the new one.
result = SecItemAdd((__bridge CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL);
NSAssert( result == noErr, @"Couldn't add the Keychain Item." );

result is at -50. The SecItemAdd is a lib method. As I was expecting, this is somehow related to the KeyChain handling directly...

keychainItemData contains: enter image description here

2
What do you mean without any code? Do you want me to copy and paste the entire Wrapper, which I have linked above, again? I have showed you exactly what I have done. (Its Apple's wrapper, its not 3rd party. click on the given link, before spam commenting here)Houman
Daij-Djan, I don't know if you are having a bad day or you are simply acting childish. First you are spam commenting, without reason you start downvoting/close, and then delete your own comments to not be traced back. If you don't want to help, its fine. What you do is not helpful, nor professional.Houman
Use the debugger and look at the return value of SecItemAdd (update the log statement to include the result code). Then search on the "Couldn't add the Keychain Item" error message and find ones referencing the same error code. There seem to be several possible causes. The error code will narrow it down a lot.rmaddy
@rmaddy Many Thanks for help. I have updated the question. The error code is -50.Houman
And a quick look at the docs states that -50 means "One or more parameters passed to the function were not valid."rmaddy

2 Answers

15
votes

I couldn't get this Apple example for Keychain wrapper work any longer. Luckily further research into this matter revealed this solution, which worked for me.

Beware the original answer to the solution is not ARC'ed, however someone was so kind to create an ARC'ed version on Github. I used that one and works like a charm.

It is a wrapper around the keychain, that works even simpler than the original one.

Hope this helps others with a similar problem.

5
votes

I had the same error when running the App on the Simulator, but it worked perfectly on the device.

In order to fix the problem with the simulator I had to turn on "Share keychain entitlement".

Share keychain entitlement