NSURLCredential and NSURLConnection

3k views Asked by At

I have been trying to search for a way to unset the credentials once you set a NSURLCredential with a NSURLConnection that is using NSURLCredentialPersistenceForSession, but I couldn't find a working solution. Removing the NSURLCredential from the NSURLCredentialStorage only removes it from the storage and not from the NSURLConnection cache. I tried turning cache off and it still keeps it. I need it to be NSURLCredentialPersistenceForSession as I don't want it to be uploading the large data then getting back the you need to authenticate message then authenticating with NSURLConnection and then resending the large data, I just want to authenticate once and send the large data once. I have a way to authenticate before sending the large data by checking some properties, but that doesn't allow me to logout or re-ask for authentication. I'm writing a WebDav client just so you understand where I stand, and the reason I need to unset the credentials is if someone has multiple accounts on the WebDav server and wants to login to another account. I tried looking into the cookies to see if it set something there, but it doesn't. I know it's only for the session, which means once your quit and relaunch the application, you can login as the other user. But that may confuse some people. I thought about writing my own Authentication system, but I wouldn't know how long that'll take.

Sorry if the above message is too long, I am just making sure I explain everything in detail so someone can try to help me with a valid answer and not a, go here leading me to something I tried.

Thanks for any help,
Mr. Gecko.

Update: Example code.

CFHTTPMessageRef message = [self httpMessageFromResponse:response];
authentication = CFHTTPAuthenticationCreateFromResponse(kCFAllocatorDefault, message);

CFHTTPMessageRef message = [self httpMessageFromRequest:request];
CFStreamError error;
CFHTTPMessageApplyCredentials(message, authentication, (CFStringRef)[credentials user], (CFStringRef)[credentials password], &error);
NSLog(@"%d", error.error); // Returns -1000
CFStringRef value = CFHTTPMessageCopyHeaderFieldValue(message, CFSTR("Authorization"));
NSLog(@"%@", (NSString *)value); // Returns NULL
if (value!=NULL)
 CFRelease(value);

Update: Code that I tried with removing credentials.

- (void)resetCredentials {
    NSURLCredentialStorage *store = [NSURLCredentialStorage sharedCredentialStorage];
    NSDictionary *allCredentials = [store allCredentials];
    NSArray *keys = [allCredentials allKeys];
    for (int i=0; i<[keys count]; i++) {
        NSURLProtectionSpace *protectionSpace = [keys objectAtIndex:i];
        NSDictionary *userToCredentialMap = [store credentialsForProtectionSpace:protectionSpace];
        NSArray *mapKeys = [userToCredentialMap allKeys];
        for (int u=0; u<[mapKeys count]; u++) {
            NSString *user = [mapKeys objectAtIndex:u];
            NSURLCredential *credential = [userToCredentialMap objectForKey:user];
            NSLog(@"%@", credential);
            [store removeCredential:credential forProtectionSpace:protectionSpace];
        }
    }
}
1

There are 1 answers

1
Kurt On

I'm working with a webdav server and had a similar issue. I found a solution within the sample code for apple's AdvancedURLConnection's project. It appears that the secret is to iterate over the protection spaces and then the credentials for each space. It's probably needlessly over complex but it works for me.

NSURLCredentialStorage *store = [NSURLCredentialStorage sharedCredentialStorage];
assert(store != nil);
for (NSURLProtectionSpace *protectionSpace in [store allCredentials]) {
    NSDictionary *userToCredentialMap = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:protectionSpace];
    assert(userToCredentialMap != nil);
    for (NSString *user in userToCredentialMap) {
        NSURLCredential *credential = [userToCredentialMap objectForKey:user];
        assert(credential != nil);
        [store removeCredential:credential forProtectionSpace:protectionSpace];
    }
}