I use a Multi View, tabbed app. From the FirstViewController, I use PresentViewController to display LoginViewController.
On LoginViewController, I'm using Keychain to save a username and a password when a user logs in on my app.
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:#"LoginInfos" accessGroup:nil];
[keychainItem setObject:_password forKey:(__bridge id)(kSecValueData)];
[keychainItem setObject:_pseudo forKey:(__bridge id)(kSecAttrAccount)];
Now, I'd like to be able to check on FirstViewController if something is set in the keychain, and if so, obviously NOT display LoginViewController. But when I try to access the keychain from FirstViewController, even after doing #import 'KeychainItemWrapper.h', I get an error saying I'm using an undeclared identifier 'keychainItem'.
NSString *mdp = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSString *username = [keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];
How can I access the info stored in the Keychain from another view? And is there a better solution (for eg, a global variable?) to check if a user is logged in?
It sounds like you just need to initialize an instance of KeychainItemWrapper in your FirstViewController... Just do:
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:#"LoginInfos" accessGroup:nil];
again before you try retrieving values from it.
Related
I used KeychainItemWrapper for keychain storage.Everything is working fine when i use the forkey:(__bridge id)kSecAttrAccount.But when i use forKey:(__bridge id)(kSecValueData)] app is crashing showing this message in console *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Couldn't add the Keychain Item.'
- (IBAction)saveOne:(id)sender
{
// save edits
keychainItemWrapper1 = [[KeychainItemWrapper alloc] initWithIdentifier:#"one" accessGroup:nil];
[keychainItemWrapper1 setObject:[userOne text] forKey:(__bridge id)(kSecValueData)];
keychainItemWrapper2 = [[KeychainItemWrapper alloc] initWithIdentifier:#"two" accessGroup:nil];
[keychainItemWrapper2 setObject:[userTwo text] forKey:(__bridge id)kSecValueData];
keychainItemWrapper3 = [[KeychainItemWrapper alloc] initWithIdentifier:#"three" accessGroup:nil];
[keychainItemWrapper3 setObject:[userThree text] forKey:(__bridge id)kSecValueData];
}
-(IBAction)reset:(id)sender{
keychainItemWrapper1 = [[KeychainItemWrapper alloc] initWithIdentifier:#"one" accessGroup:nil];
[keychainItemWrapper1 resetKeychainItem];
keychainItemWrapper2 = [[KeychainItemWrapper alloc] initWithIdentifier:#"two" accessGroup:nil];
[keychainItemWrapper2 resetKeychainItem];
keychainItemWrapper3 = [[KeychainItemWrapper alloc] initWithIdentifier:#"three" accessGroup:nil];
[keychainItemWrapper3 resetKeychainItem];
}
can anyone please help me with this.
Thanks in advance.
You may need to look in your - (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert method within your KeychainItemWrapper class. Specifically look at your NSMutableDictionary that you are using to write to your keychain. Have you set the key as kSecValueData for the dictionary that you use within the function SecItemAdd or SecItemUpdate? If not, that may be where the problem lies.
I write very secure application (for Bank) and I keep the private key in the Keychain.
I keep the Private key using the following code:
+(void)savePrivatekey:(NSString *)Key
{
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"pKey" accessGroup:nil];
[keychain setObject:Key forKey:(id)kSecValueData];
[keychain release];
}
and for get the private key using the following code:
+(NSString *)privateKey
{
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"pKey"accessGroup:nil];
NSString *privateKey = [keychain objectForKey:(id)kSecValueData];
[keychain release];
return privateKey;
}
i don't save the private key in local variable from security reasons.
because every call to server I need the private key i call to to function
"GetPrivateKey" a lot of times.
Maybe that's why sometimes i get from the keychain empty string.
i can't think of why this might happen.
I noticed that in most cases this happens when the application return from background but no only...
thanks...
I opened ticket at Apple's engineers and they responded to me:
Are you setting the kSecAttrAccessible attribute when you create the keychain item initially?
I always create the same shape keychain:
KeychainItemWrapper * keychain = [[KeychainItemWrapper alloc] initWithIdentifier: # "pKey" accessGroup: nil];
Does anyone know what their intent?
thanks...
I answered my own question a while back regarding this. I'm not sure if this is your exact problem as your code seems to look/work fine. So regarding your keychain access, I'm guessing it is a bit different. This may or may not help, but might steer you in the right direction.
iOS KeyChain not retrieving values from background
If your class is using ARC the following works for me every time.
KeychainItemWrapper *testKeychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"AppUniqueID" accessGroup:nil];
NSString *privateKey = [testKeychain objectForKey:(__bridge id)(kSecValueData)];
NSLog(#"Private Key: %# \n", privateKey);
I have this code currently storing the information into the iPhone keychain. How can I check with a simple if statement if there is something under the same name already stored there to prevent double storage and to tell me if this is the first time the user is using the app?
KeychainItemWrapper* keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"KeychainTest" accessGroup:nil];
[keychain setObject:username.text forKey:(__bridge id)(kSecAttrAccount)];
[keychain setObject:password.text forKey:(__bridge id)(kSecValueData)];
keychain = nil;
usernameAll = [keychain objectForKey:(__bridge id)kSecAttrAccount];
passwordAll = [keychain objectForKey:(__bridge id)kSecValueData];
You won't cause double storage. You will overwrite any existing value.
Create your keychain object, then call objectForKey:. If the result is nil then you know that there is no existing value for the key.
KeychainItemWrapper* keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"KeychainTest" accessGroup:nil];
if ([keychain objectForKey:(__bridge id)(kSecAttrAccount)]) {
// existing value
} else {
// no existing value
}
Checking to see if a user is using an app for the first time is usually done by writing a value to NSUserDefaults the first time the app is used. On startup, this value is checked. If the value exists, it's not the first run. If you need this check to survive an app deletion and reinstall, then use the keychain instead of NSUserDefaults to store this flag.
in my app I can save an read fine 1 password store in the keychain using this code
// save password
[keychainItem setObject:textFieldPassword.text forKey:(__bridge id)(kSecValueData)];
//get pasword from keychain
NSString *_password = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
My question is: how can I store more than 1 password at a time in the keychain?
Keychain programming is hard. I use a wrapper class called SFHFKeychainUtils. It has very simple class methods for storing and retrieving passwords.
Check it out: https://github.com/ldandersen/scifihifi-iphone/tree/master/security
You store items with keys you make up. So you could have #"WiFiPasswordKey", #"LoginPasswordKey", etc.
Thank you all for your answers.
Here the solution I used:
adding to my project the files KeychainItemWrapper.h/m
allocating 2 keychain items:
//aloc for user password
keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:#"passowrdKey1" accessGroup:nil];
//aloc for user password2
keychainItem2 = [[KeychainItemWrapper alloc] initWithIdentifier:#"passowrdKey1" accessGroup:nil];
then just use this to read/write
//WRITE
// save password
[keychainItem setObject:#"password1" forKey:(__bridge id)(kSecValueData)];
// save password2
[keychainItem2 setObject:#"password2" forKey:(__bridge id)(kSecValueData)];
//READ
//get pasword from keychain
NSString *_pass = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
//get pasword from keychain
NSString *_pass2 = [keychainItem2 objectForKey:(__bridge id)(kSecValueData)];
I am using Keychainwrapper class downloaded from Apple documentation for storing login information like password. In my apps when user click on sign in button, I am storing in key chain like below...
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc]
initWithIdentifier : #"vmo_login" accessGroup:nil];
[keychainItem setObject:email_id.text forKey:(__bridge NSString*)kSecAttrAccount];
[keychainItem setObject:password.text forKey:(__bridge NSString*)kSecValueData];
And if user click on sign out I am exiting application with exit(1). Once application is launched again, I am reading from keychain like below..
NSString *loc_email1 = [keychainItem objectForKey:(__bridge NSString*)kSecAttrAccount];
NSString *loc_pwd1 = [keychainItem objectForKey:(__bridge NSString*)kSecValueData];
I have not got what I have stored below, it returns NULL. Any Idea?.
thanks.
I have found the problem..
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc]
initWithIdentifier : #"<need to give same as when we write>" accessGroup:nil];
Working fine now.