Not possible for NSURLConnection to ignore shared NSURLCredentialStorage
||Date Originated:||15-May-2007 07:10 AM|
15-May-2007 07:10 AM Dave Dribin:
When NSURLConnection needs credentials to authenticate a request, it first consults the shared NSURLCredentialStorage. If no credentials are found, the connection:didReceiveAuthenticationChallenge: delegate method gets called. The problem is that the if credentials *are* found in the shared credential storage, the delegate has no way of overriding them. If another app sets credentials in the shared storage, there is no way for my own app to set the credentials to a different username/password
Discussion on the macnetworkprog list:
The use case for this is integration with a web-based API protected with HTTP authentication. A client may need to access multiple user accounts. Or two competing clients may need to access different accounts. My app should have complete control of the username and password used in the HTTP authentication.
Steps to Reproduce:
* In one app, set the default credentials using setDefaultCredential:forProtectionSpace: on the shared NSURLCredentialStorage for a Basic Auth protected URL.
* In another app, try to accesss the protected URL using NSURLConnection.
In the second app, the connection:didReceiveAuthenticationChallenge: delegate should get called to allow it to set the username and password.
The username and password are pulled from the shared NSURLCredentialStorage. The standard Keychain access dialog is presented the user, asking them to allow access by the second app. If the user replies "Allow Once" or "Allow Always", then the username/password are pulled from Keychain. The second app has no way to override this, and thus cannot use a different username/password credential than one already saved.
It's 100% reproducible.
The only workaround I've found is to override the behavior of NSURLCredentialStorage by hacking the Obj-C runtime. The simplest way is to use a category:
static NSMutableDictionary * sDefaultCredentials;
sDefaultCredentials = [[NSMutableDictionary alloc] init];;
@implementation NSURLCredentialStorage (SharedOverride)
- (NSURLCredential *) defaultCredentialForProtectionSpace: (NSURLProtectionSpace *) protectionSpace;
return [sDefaultCredentials objectForKey: protectionSpace];
- (void) setDefaultCredential: (NSURLCredential *) credential
forProtectionSpace: (NSURLProtectionSpace *) protectionSpace;
[sDefaultCredentials setObject: credential forKey: protectionSpace];
The downside to this is that the original implementation of these methods become inaccesible. Class posing or method swizzling could solve this, if needed. But in the end, none of this runtime hacking should be necessary.
Reports posted here will not necessarily be seen by Apple.
All problems should be submitted at bugreport.apple.com before they are posted here.
Please only post information for Radars that you have filed yourself, and please do
not include Apple confidential information in your posts. Thank you!