Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use AFNetworking 2 with Digest Authentication

I've been searching for "AFNetworking 2 with Digest Authentication" for a while and haven't found useful discussions about it (except this one, but unfortunately it looks like it's for AFNetworking 1).

Here's my code without authentication:

NSString* apiURL = @"https://api.example.com/WS.asmx";
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager
    GET:apiURL 
    parameters: [NSDictionary dictionaryWithObjectsAndKeys:@"ID", 1234 , nil]
    success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"JSON: %@", responseObject);
    }
    failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"WS request failed: %@", error);
    }
];

Where and how can Digest Auth code kick in?

like image 281
AsyncMoksha Avatar asked Oct 21 '22 13:10

AsyncMoksha


1 Answers

This question is a bit old, but I had to do just this and I couldn't find any built in way to handle it. The solution I used was to edit AFNetworkings AFURLSessionManager.m. Basically you modify this delegate method to support http digest, heres a full example.

    - (void)URLSession:(NSURLSession *)session
                  task:(NSURLSessionTask *)task
    didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
     completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
    {
        NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        __block NSURLCredential *credential = nil;

        if (self.taskDidReceiveAuthenticationChallenge) {
            disposition = self.taskDidReceiveAuthenticationChallenge(session, task, challenge, &credential);
        } else {
            if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
                if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
                    disposition = NSURLSessionAuthChallengeUseCredential;
                    credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                } else {
                    disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
                }
            } else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest]) {
                NSDictionary *userkeys = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:challenge.protectionSpace];

                credential = [userkeys objectForKey:(NSString *)[[userkeys allKeys] objectAtIndex: 0]];
                if (credential) {
                    disposition = NSURLSessionAuthChallengeUseCredential;
                } else {
                    disposition = NSURLSessionAuthChallengePerformDefaultHandling;
                }
            }else {
                disposition = NSURLSessionAuthChallengePerformDefaultHandling;
            }
        }

        if (completionHandler) {
            completionHandler(disposition, credential);
        }
    }

You will need to add a credential to the sharedCredentialStorage before this challenge. You can check the apple docs for that as it is fairly straight forward but make sure the protection space matches up exactly, including the realm. I hope it helps someone.

like image 194
bob Avatar answered Oct 24 '22 06:10

bob