I am converting an iOS app from NSURLConnection to NSURLSession.
The server is interacts with uses both https (cert signed by a recognised CA) and Basic Authentication.
Rather than using completion blocks for the data return, I'm using custom delegates. I've seen elsewhere, that using custom delegates means I should response to AuthenticationChallenges rather than rely on CredentialStorage (not that that works either, but that's another issue).
My problem is that the challenge occurs once for the ServerTrust, but doesn't get called again for the HttpBasic Authentication. So, my sessions time out.
I've tried using completion blocks for the 'defaultSession dataTaskWithRequest' rather than custom delegates, just to see if I can get past this point, but it makes no difference. I also tried using CredentialStorage for the HttpBasic credentials but, as mentioned above, no joy.
This has got me stumped. Any ideas?
(void)URLSession:(NSURLSession *)connection
// task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler
{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: Using SSL");
#endif // DEBUG
if ([challenge.protectionSpace.host isEqualToString:HOST])
{
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: Using Protection Space Host - %@", HOST);
#endif // DEBUG
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
else
{
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
}
else
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic] ||
[challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest])
{
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: (Basic / Digest) #%ld - user: %@, password: %@",
(long)[challenge previousFailureCount], USERNAME, PASSWORD);
#endif // DEBUG
if ([challenge previousFailureCount] == 0)
{
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: previousFailureCount == 0");
#endif // DEBUG
NSURLCredential *newCredential;
newCredential = [NSURLCredential credentialWithUser:USERNAME
password:PASSWORD
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}
else
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
// inform the user that the user name and password
// in the preferences are incorrect
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: Failed Authentication");
#endif // DEBUG
// ...error will be handled by connection didFailWithError
}
}
#ifdef DEBUG
else
{
NSLog(@"didReceiveChallenge: Not handled!");
}
#endif // DEBUG
}
In no particular order:
I'm not sure if there are other bugs in the code, but all three of those could cause serious misbehavior, and one of them is a major security hole. Start by fixing those issues, and if it still doesn't work, add further comments. :-)
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