I'm working on an application where when a user selects a menu item they are brought to a webpage. The webpage requires authentication, and to make things simpler for the user I would like to pass along their authentication information to Safari/Firefox/Chrome that is stored in my application.
I've tried creating generic and internet keychain items, which show up beautifully in Keychain Access, but no web browsers pick up on them.
I've noticed that the keychain items being stored for the browsers have the type "Web Form Password".
When I try to create a keychain item with the type 'kSecAuthenticationTypeHTMLForm' it shows in Keychain Access as 'internet password'. I've modified some code from the EMKeychain class:
+ (EMInternetKeychainItem *)addInternetKeychainItemForServer:(NSString *)server
withUsername:(NSString *)username
password:(NSString *)password
path:(NSString *)path
port:(NSInteger)port
protocol:(SecProtocolType)protocol
{
if (!username || !server || !password)
return nil;
const char *serverCString = [server UTF8String];
const char *usernameCString = [username UTF8String];
const char *passwordCString = [password UTF8String];
const char *pathCString = [path UTF8String];
if (!path || [path length] == 0)
pathCString = "";
SecKeychainItemRef item = nil;
OSStatus returnStatus = SecKeychainAddInternetPassword(NULL, strlen(serverCString), serverCString, 0, NULL, strlen(usernameCString), usernameCString, strlen(pathCString), pathCString, port, protocol, kSecAuthenticationTypeHTMLForm, strlen(passwordCString), (void *)passwordCString, &item);
if (returnStatus != noErr || !item)
{
if (_logsErrors)
NSLog(@"Error (%@) - %s", NSStringFromSelector(_cmd), GetMacOSStatusErrorString(returnStatus));
return nil;
}
return [EMInternetKeychainItem _internetKeychainItemWithCoreKeychainItem:item forServer:server username:username password:password path:path port:port protocol:protocol];
}
The most likely problem is that the keychain entry is created with an ACL that does not give access to its contents to Safari. (I think Chrome and Firefox use their own proprietary password databases instead of the keychain, so modifying the keychain won't affect those browsers.)
Try using SecKeychainItemSetAccess
to permit access to all applications. I use the following code to create such a permissive SecAccess object:
// Create an access object.
SecAccessRef access;
status = SecAccessCreate(CFSTR("item description"),
NULL, // Only this app has access (this'll get changed in a moment)
&access);
if (status) { ... }
// Override access control to provide full access to all applications.
NSArray *aclList = nil;
status = SecAccessCopyACLList(access, (CFArrayRef *)&aclList);
if (status) { ... }
for (id object in aclList) { // will do just one iteration
SecACLRef acl = (SecACLRef)object;
CFArrayRef applist = NULL;
CFStringRef desc = NULL;
CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cakps;
status = SecACLCopySimpleContents(acl, &applist, &desc, &cakps);
if (status) { ... }
status = SecACLSetSimpleContents(acl,
NULL, // All applications.
desc,
&cakps);
if (status) { ... }
if (applist != NULL)
CFRelease(applist);
if (desc != NULL)
CFRelease(desc);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With