How to do NTLM Authentication in iOS

One of the more vexing things in iOS is handling NTLM authentication.  There aren't very many good code examples, so this article will walk you through the process using an NSURLConnection object.

First off, you need to initialize a new NSURLConnection object with a delegate:

- (void) someMethod { 
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL urlWithString:@"someURL"] 
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
    [request release]; 
    [connection release]; 
}

This is all pretty straight forward.  It's in the delegate methods of the NSURLConnection where all the magic happens.  The delegate method of the NSURLConnection we're most concerned with is connection:didReceiveAuthenticationChallenge:.

- (void) connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 
    if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodNTLM) {
        /*    This is very, very important to check.  Depending on how your security policies are setup, you could lock your user out of his or her account by trying to use the wrong credentials too many times in a row.    */ 
        if ([challenge previousFailureCount] > 0)  { 
            [[challenge sender] cancelAuthenticationChallenge:challenge]; 
            UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Invalid Credentials" 
                                                            message:@"The credentials you saved for your account are invalid." 
                                                           delegate:nil 
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil]; 

            [alert show]; 
            [alert release]; 
        } else {
             NSURLCredential *credential = [NSURLCredential credentialWithUser:@"someUser" password:@"somePassword" persistence:NSURLCredentialPersistenceForSession]
             [[challenge sender]  useCredential:credential forAuthenticationChallenge:challenge]; 
        } 
    } else  { 
        // Do whatever you want here, for educational purposes, I'm just going to cancel the challenge 
        [[challenge sender] cancelAuthenticationChallenge:challenge]; 
    } 
}

In the example above, I have hard coded the credentials.  You can set your own delegate for obtaining user credentials, say, through a UIAlertView or credential store, but this example should be good enough to get the general idea.

Posted on Feb 21
Written by Wayne Hartman