Thursday, May 12, 2016

Objective C Authentication Challenges

We frequently call web services in our applications. Servers throw different types of authentication challenges based on the authentication methods with which they were designed for security purposes.

Here are the different types of authentication challenges.

  • NSURLAuthenticationMethodDefault;
  • NSURLAuthenticationMethodHTTPBasic;
  • NSURLAuthenticationMethodHTTPDigest;
  • NSURLAuthenticationMethodHTMLForm;
  • NSURLAuthenticationMethodNTLM 
  • NSURLAuthenticationMethodNegotiate 
  • NSURLAuthenticationMethodServerTrust




                         


We need to handle them in the authentication challenge delegate methods by checking the challenge type. Not every time we get the user's authentication challenge.

In this post, Let's see how to handle NSURLAuthenticationMethodNTLM and NSURLAuthenticationMethodServerTrust handling in NSURLSession's didReceiveChallenge delegate method.

NSURLAuthenticationMethodServerTrust


We will get this Authentication method, When we are hitting a HTTPS server.



-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(    NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:
                        NSURLAuthenticationMethodServerTrust]) {   //Server trust challenge
        
        NSURLCredential *credential =     
                        [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                            [[challenge senderuseCredential:credential forAuthenticationChallenge:challenge];
        
    }
}




As shown in the above code, Check every time the type of challenge, I mean the type the Authentication challenge we are getting as delegate call back and respond to that challenge 
accordingly.

NSURLAuthenticationMethodNTLM:



If the server we are hitting is having NTLM authentication configured, We need to pass the logged In user's credentials in the challenge delegate method.



-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(    NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler

{
    
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:    
                          NSURLAuthenticationMethodServerTrust]) {   //Server trust challenge
        
        NSURLCredential *credential = 
                           [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];

        [[challenge senderuseCredential:credential forAuthenticationChallenge:challenge];
        
    }
    
    else{  //NTLM authentication challenge
    
            NSString *userName = @"username";
            NSString *pwd =  @"password";
            
            if ([challenge previousFailureCount] == 0) {
      
                    
                    NSURLCredential *cred = 
                                   [NSURLCredential credentialWithUser:userName password:pwd 
                                                         persistence:NSURLCredentialPersistenceNone];

                    completionHandler(NSURLSessionAuthChallengeUseCredential, cred);
                
                
            }
            
            else {
     
                   completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallengenil);
            }
        
    }


}



That's how we need to check the challenge type and respond accordingly.



                         


Hope this post is useful. Feel free to comment in case of any queries.