10

I am trying to load a https:// webpage using UIWebView in iOS 9+ and it's giving following error :

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802) CFNetwork SSLHandshake failed (-9802)

I have already tried various mentioned approaches of using NSURLConnection first to handle authentication challenge using connection:willSendRequestForAuthenticationChallenge: method.

Although this is working fine for direct requests, but (here the actual problem begins) this is not working in case of webpages that redirect to another page with different domain.

So for instance, initially I load the UIWebView with call to https://example.com and this page then redirects to https://someothersecuredomain.com. This is were the connection fails and connection:willSendRequestForAuthenticationChallenge: is not called.

Below is my implementation :

- (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    // Load webview with request url and parameters
    NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
    [request setHTTPBody:postBody];
    [request setHTTPMethod: @"POST"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

    self.webView.delegate = self;
    [self.webView loadRequest: request];

    _BaseRequestURL = url;
}

#pragma mark UIWebView delegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {

    if (![[request.URL absoluteString] isEqualToString:[_FailedRequest.URL absoluteString]]) {

        _FailedRequest = request;
        (void)[[NSURLConnection alloc] initWithRequest:request delegate:self];
        return NO;
    }

    return YES;
}

#pragma mark - NSURLConnectionDataDelegate methods

-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSURL *baseURL = [_FailedRequest URL];
        if ([challenge.protectionSpace.host isEqualToString:baseURL.host]) {
            NSLog(@"trusting connection to host %@", challenge.protectionSpace.host);
            [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
        } else
            NSLog(@"Not trusting connection to host %@", challenge.protectionSpace.host);
    }
    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)pResponse {

    [connection cancel];
    [self.webView loadRequest:_FailedRequest];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {

    NSLog(@"connection error : %@", error);
}

And here is the Connection error logged :

Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSUnderlyingError=0x138643250 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSErrorFailingURLStringKey=https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamPropertySSLClientCertificateState=0, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., _kCFStreamErrorDomainKey=3, NSErrorFailingURLKey=https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction, _kCFStreamErrorCodeKey=-9802}}, NSErrorFailingURLStringKey=https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction, NSErrorFailingURLKey=https://secure.ccavenue.com/transaction/transaction.do?command=initiateTransaction, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.}

As per iOS 9's App Transport Security, I have already added both the domains to the list of Exception domains in my Info.plist.

Which is like this :

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>example.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
        </dict>
        <key>secure.ccavenue.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
        </dict>
    </dict>
</dict>

I am really stuck in this and any help would be appreciated.

PS. Already tried these questions : Question 1, Question 2, Question 3, Question 4 and Question 5

Community
  • 1
  • 1
UditS
  • 1,936
  • 17
  • 37

0 Answers0