Skip to content

Instantly share code, notes, and snippets.

@AquaGeek
Created October 22, 2012 21:28
Show Gist options
  • Select an option

  • Save AquaGeek/3934520 to your computer and use it in GitHub Desktop.

Select an option

Save AquaGeek/3934520 to your computer and use it in GitHub Desktop.
Keychain
- (BOOL)checkKeychainForAuthCredentials
{
NSMutableDictionary *keychainQuery = [self keychainSearchDictionary];
// Fire off the query
OSStatus keychainErr = noErr;
CFDictionaryRef outDictionary;
keychainErr = SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&outDictionary);
if (keychainErr == noErr && outDictionary != NULL)
{
// Query the keychain again for the password data
[keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
[keychainQuery removeObjectForKey:(__bridge id)kSecReturnAttributes];
CFDataRef passwordData = NULL;
keychainErr = SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&passwordData);
if (keychainErr == noErr)
{
NSString *username = [((__bridge NSDictionary *)outDictionary) objectForKey:(__bridge id)kSecAttrAccount];
// Convert the password to an NSString and add it to the return dictionary
NSString *password = [[NSString alloc] initWithBytes:[(__bridge NSData *)passwordData bytes]
length:[(__bridge NSData *)passwordData length]
encoding:NSUTF8StringEncoding];
NSLog(@"Username: %@ || Password: %@", username, password);
// TODO: Validate the credentials?
}
else if (keychainErr == errSecItemNotFound)
{
// TODO: Anything?
}
}
else if (keychainErr == errSecItemNotFound)
{
// TODO: Anything?
}
return NO;
}
- (BOOL)saveAuthCredentialsToKeychain:(NSDictionary *)credentials
{
NSMutableDictionary *keychainQuery = [self keychainSearchDictionary];
// Fire off the query
OSErr keychainErr = noErr;
// Try to find an existing item
CFDictionaryRef outDictionary;
keychainErr = SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&outDictionary);
NSString *username = [credentials objectForKey:@"username"];
NSData *passwordData = [[credentials objectForKey:@"password"] dataUsingEncoding:NSUTF8StringEncoding];
if (keychainErr == errSecSuccess)
{
// Update the item (via the response we got back from the call to SecItemCopyMatching)
NSDictionary *updatedCredentials = @{ (__bridge id)kSecAttrAccount : username, (__bridge id)kSecValueData : passwordData };
keychainErr = SecItemUpdate(outDictionary, (__bridge CFDictionaryRef)updatedCredentials);
return (keychainErr == noErr);
}
else
{
// Create the item
[keychainQuery setObject:username forKey:(__bridge id)kSecAttrAccount];
[keychainQuery setObject:passwordData forKey:(__bridge id)kSecValueData];
keychainErr = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
return (keychainErr == noErr);
}
}
- (NSMutableDictionary *)keychainSearchDictionary
{
NSMutableDictionary *keychainQuery = [@{ } mutableCopy];
// We're looking for a generic password
[keychainQuery setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
// For the Fly Delta app
[keychainQuery setObject:@"My Awesome Service" forKey:(__bridge id)kSecAttrService];
// We only want the first match
[keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
// Return the attributes of the keychain item (if found)
[keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes];
return keychainQuery;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment