Using authentication headers with a NSURLMutableRequest in IOS

When you have your app running on your IOS device open a connection to a server, sometimes you will want to have the connection be a secure connection using HTTPS. This blog entry discusses how to setup your NSURLSession and NSURLMutableRequest object to setup the fields in the HTTP headers to open a secure HTTPS connection to your server. In my latest project with Narrative Technologies, the litho reader application required a secure connection to the servers in order to control the access to the users downloads, wish lists, and other items that were unique to each subscriber. We used the HTTPS authentication to control access to these items on the server.

Below is a selector that we use to download something from a server using a secure connection.


-(void)downloadSomething
{
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    // if you are handling JSON requests, you really should set the HTTP accept header to accept 
    // a JSON formatted response.  Otherwise, the IOS operating system will determine which is the most 
    // suitable and you will get either JSON or XML formatted data in your response object.
    [config setHTTPAdditionalHeaders:@{@"Accept" : @"application/json"}];

    // I don't like to allow caching when sending or receiving secure data.
    config.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

    // setup the URLSession with the correct accept header.
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config];

    if (session) {
        NSURL *url = [NSURL URLWithString:@"https://www.conedogers.com"];
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
        
        if (request) {

            // once you have your request object, you need to set the Authorization header field
            [request setValue:[self getHTTPAuthorizationHeader] forHTTPHeaderField:@"Authorization"];
            [request setHTTPMethod:@"GET"];
            
            [[session dataTaskWithRequest:request
                        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                            
                            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
                            NSString *contentType = [httpResponse.allHeaderFields valueForKey:@"Content-Type"];

                            // parse the data depending on the Content-Type
                            if (contentType) {
                                if ([contentType caseInsensitiveCompare:@"application/json"] == NSOrderedSame) {
                                    // parse your content as a JSON formatted response
                                }
                                else if ([contentType caseInsensitiveCompare:@"application/xml"] == NSOrderedSame) {
                                    // parse your content as a XML formatted response
                                }
                                else {
                                    NSLog(@"%@ unknown content-type http Status %ld", contentType, (long)httpResponse.statusCode);
                                }
                            }
                            else {
                                NSLog(@"no content-type defined");
                            }
                        }] resume];
        }
    }
}

So that’s how we setup the NSURLSession and NSURLRequest objects to open a HTTPS connection to your server and process the results in a completion block. The technique is similar when using a background download task in a URLSession. But what do we need to do to create the proper authentication header for this example? For this sample we are using Basic authentication, so the string that we need to send to the server is formatted like this: “Basic ==”. For this example we assume that the server uses your email to track your login user on the server and we then have a password that would have been either assigned or registered on the server when the user signed up.



-(NSString *)getHTTPAuthorizationHeader
{
    // this creates the credentials string that we need for the basic authentication
    NSString *authenticationString = [NSString stringWithFormat:@"%@:%@", self.email, self.password];
    // convert it to a data stream
    NSData *authenticationData = [authenticationString dataUsingEncoding:NSUTF8StringEncoding];
    // encode the stream with base64 encoding
    NSString *authenticationValue = [authenticationData base64EncodedStringWithOptions:kNilOptions];
    
    // now return the complete authorization header formatted for basic authentication.
    return [NSString stringWithFormat:@"Basic %@==", authenticationValue];
}

Objective-C and IOS make it very easy to construct authorization headers for a secure connection