Authentication invocation method not called when using NSURLSession custom delegate

I am working on an iOS application that connects to ASP.NET web API through Restful services. I want to use a custom delegate to perform authentication. But the delegate method is not called.

An HTTP request is written as follows in the view controller:

- (IBAction)test:(UIButton *)sender { //Get Bearer Token KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"BearerToken" accessGroup:nil]; NSString *bearerToken = [keychainItem objectForKey:(__bridge id)(kSecValueData)]; //Configure request NSURL *url = [NSURL URLWithString:@"......"]; //Replace the .... with real IP Address NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"GET"]; [request setValue:[NSString stringWithFormat:@"Bearer %@", bearerToken] forHTTPHeaderField:@"Authorization"]; //Configure session NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AuthChallengeDelegate *authChallengeDel = [[AuthChallengeDelegate alloc] init]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:authChallengeDel delegateQueue:nil]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request]; [task resume]; } 

In the AuthChallengeDelegate class, I performed the following method:

 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { NSLog(@"%@", response); } - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { NSLog(@"did receive challenge method called"); NSLog(@"%@", challenge.protectionSpace.authenticationMethod); } 

The first method (didReceiveResponse) is called, and the response status code is 401 with "Www-Authenticate" = Bearer in the header field. But the second method (didReceiveChallenge) is not called. Can anyone here give me an idea of ​​why it is not called?

(I use Xcode 6 and model in iOS8)

Thanks.

+6
source share
5 answers

From the iOS Developer Library

Important. URL loading classes do not call their delegates to process request requests unless the server response contains a WWW-Authenticate header.

From where we understand that didReceiveChallenge methods should be called BUT , the URLSession:task:didReceiveChallenge:completionHandler: method is called only when the header looks like 'WWW-Authenticate':'Basic'

I did not find a solution how to handle authentication on tokens, where the header is 'WWW-Authenticate':'Bearer' , as in the question, using authentication problems.

+8
source

NSURLSession delegates have two different call / response handlers. The first one you implement is at the session level and basically handles authentication at the server level. From the documentation :

  • For session level tasks - NSURLAuthenticationMethodNTLM, NSURLAuthenticationMethodNegotiate, NSURLAuthenticationMethodClientCertificate or NSURLAuthenticationMethodServerTrust - the NSURLSession object invokes session delegates URLSession: didReceiveChallenge: completeHandler: method. If your application does not provide a session delegation method, the NSURLSession object invokes the task delegates URLSession: task: didReceiveChallenge: completeHandler: method to process the call.

  • For non-session tasks (all others), the NSURLSession object invokes session delegates URLSession: task: didReceiveChallenge: completeHandler: method to handle the call. If your application provides a session delegate and you need to handle authentication, you must either process authentication at the task level or provide a task-level handler that will explicitly call a handler for each session. Session delegates URLSession: didReceiveChallenge: completeHandler: method is not called for tasks not associated with the session.

So, you probably want to handle task-level validation by adding protocol support for the delegate Task for NSURLSession in the delegation object and put a handler at the task level, i.e. URLSession(_:task:didReceiveChallenge:completionHandler:) .

+4
source

I know this problem is related to iOS 8, but if you are using iOS 9, please also remember that the NSAppTransportSecurity key in Info.plist now required to target any specific domain names.

I had the same problem and used wirehark to view the TLS network layer to check which version of TLS was used by the image server that I was aiming for.

Based on this, you can add this to your Info.plist and maybe solve this problem.

 <key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>yourdomain.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> <key>NSTemporaryExceptionMinimumTLSVersion</key> <string>TLSv1.0</string> </dict> </dict> </dict> 
+2
source

if you write:

 AuthChallengeDelegate *authChallengeDel = [[AuthChallengeDelegate alloc] init]; 

authChallengeDel LOCAL, so it will be released immediately after exiting the methods. So make this property

+2
source

Try changing the delegate: authChallengeDel to delegate: self

-1
source

Source: https://habr.com/ru/post/976460/


All Articles