amazon-s3afnetworkingnsurlconnection

Getting "The certificate for this server is invalid." on iPad when loading an image from Amazon S3 (HTTPS), but no errors on simulator


I am trying to display an image that is stored on an Amazon S3 Bucket. The URL is something like https://s3.amazon.com/..../test.jpg. Whenever I do this on the iPhone simulator, the image is displayed properly. However, if I test it on the actual device itself, I keep getting:

Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “s3.amazonaws.com” which could put your confidential information at risk." UserInfo=0x20007030 {NSErrorFailingURLStringKey=https://s3.amazonaws.com/.../test.jpeg, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSErrorFailingURLKey=https://s3.amazonaws.com/.../test.jpeg, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “s3.amazonaws.com” which could put your confidential information at risk., NSUnderlyingError=0x20014d40 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “s3.amazonaws.com” which could put your confidential information at risk.", NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x1edd98a0>}


Solution

  • I was getting the same certificate error from S3, and found adding this to the NSURLConnectionDelegate fixed the problem:

    -(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
    {
       if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] &&
           [challenge.protectionSpace.host hasSuffix:@"example.com"])
       {
           // accept the certificate anyway
           [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
       }
       else
       {
           [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
       }
    }
    

    NOTE: You'll need to change 'example.com' to a domain you trust, or use a more sophisticated mechanism than 'hasSuffix'.

    FYI Apple Technote TN2232 "HTTPS Server Trust Evaluation" goes into much of the detail about why the certificate was rejected and how to handle it: https://developer.apple.com/library/ios/technotes/tn2232/_index.html

    Thanks to Gordon Henriksen for answering this at https://stackoverflow.com/a/2033823/235229, but using an older api.