16

This my first project using swift. I am usin alamofire to connect the API. I have a local copy form the API I want to use for debugging - so I can set test data - because the remote API has already real data that I can't mess with.

The problem is I am getting the below error when I try to access https://localhost:8443/MyProject

Optional(Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “localhost” which could put your confidential information at risk." UserInfo=0x7fbeb8c61ff0 {NSURLErrorFailingURLPeerTrustErrorKey=, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorCodeKey=-9813, NSUnderlyingError=0x7fbeb8ea5c00 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1202.)", NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “localhost” which could put your confidential information at risk., NSErrorFailingURLKey=https://localhost:8443/myproject/api/loginUser.pdo, NSErrorFailingURLStringKey=https://localhost:8443/myproject/api/loginUser.pdo, _kCFStreamErrorDomainKey=3})

I have found many solution most of them for Objective-c as using setAllowsAnyHTTPSCertificate or using the delegate for Connection. but I could not find an equevelent method for setAllowsAnyHTTPSCertificate in swift, and I not sure how to set the delegate to the connection while using alamofire. any ideas what I need to do?

  • I know that setAllowsAnyHTTPSCertificate is private api and will cause the project to be rejected by Apple. I want to use it only while debugging then it will be removed before the publishing the project.

Thank you in advance.

Ismail
  • 2,778
  • 2
  • 24
  • 39
  • 1
    check this https://github.com/Alamofire/Alamofire/issues/457 – tkanzakic May 11 '15 at 08:58
  • possible duplicate of [How to implement self signed certificates in Alamofire?](http://stackoverflow.com/questions/28868126/how-to-implement-self-signed-certificates-in-alamofire) – tkanzakic May 11 '15 at 08:58
  • 1
    The answer in this other question recommending either to implemnt this feature my self or use AFNetworking. I only want to use localhost for debugging perpose It will take me too long to learn and implemnt it. I don't want to use AFNetworking too. Is there any simple solution to igonor this certificate error? just like `setAllowsAnyHTTPSCertificate` in objective-c? – Ismail May 11 '15 at 09:34
  • 1
    In the link given by @tkanzakic: "At the moment, there is no direct support in Alamofire for trusting self-signed certificates or for SSL pinning." – Eric Aya May 11 '15 at 09:54
  • I see that. Thank you all. I hope someone solve it soon. – Ismail May 11 '15 at 11:03

4 Answers4

21

You can easily override the default challenge behavior in Alamofire using the SessionDelegate override closures. Here is an example of how you can allow Alamofire to accept invalid certificates:

IMPORTANT: Please do not use this in any production code. Security is VERY important and this implementation completely disregards the security mechanisms in Alamofire. Use at your own risk!

let manager = Alamofire.Manager.sharedInstance

manager.delegate.sessionDidReceiveChallenge = { session, challenge in
    var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
    var credential: NSURLCredential?

    if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
        disposition = NSURLSessionAuthChallengeDisposition.UseCredential
        credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
    } else {
        if challenge.previousFailureCount > 0 {
            disposition = .CancelAuthenticationChallenge
        } else {
            credential = manager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)

            if credential != nil {
                disposition = .UseCredential
            }
        }
    }

    return (disposition, credential)
}

We (the Alamofire TC) are going to implement TLS pinning and several other features related to security in the Alamofire 1.3.0 release.


UPDATE

The Alamofire 1.3.0 release is out and adds MUCH better support for customizing server trust authentication challenges. For further info, please check out the Security section of the README.

cnoon
  • 16,575
  • 7
  • 58
  • 66
  • Thank you for sharing this! Could you provide any direction for where this code may go? I'm new to iOS and learning this as I go. I am only turning this off to test my app. My production server is the only one at this point with a valid SSL cert and I REALLY do not want to test my app against production at this stage. – ShatyUT Jun 03 '15 at 03:40
  • This [blog](http://blog.carbonfive.com/2011/06/20/managing-ios-configurations-per-environment-in-xcode-4/) should get you going in the right direction. – cnoon Jun 03 '15 at 15:07
  • Thanks for sharing that blog. It will be very helpful but isn't really what I was asking. I'm not sure where the above code you posted is supposed to live. I've placed it in a number of places in my app but the overridden delegate method is never called. – ShatyUT Jun 03 '15 at 15:19
  • Edit submitted but I figured out why this code was not working for me. It is creating a brand new Alamofire.Manager instance and setting the delegate method on that instance. It should set the delegate method on Alamofire.Manager.sharedInstance instead so that it properly overrides the instance being used by the framework. Thank again for sharing the code, @cnoon! – ShatyUT Jun 05 '15 at 20:13
  • Sorry for the confusion @ShatyUT. In order to avoid this issue for others in the future, I updated the answer accordingly. This is a common mistake that I've seen many times on various Alamofire questions. – cnoon Jun 06 '15 at 06:21
  • I find myself really confused by the new security stuff. I found the Alamofire.ServerTrustPolicyManager, and I want to set it to use the "disableEvaluation" for my localhost so that I can step through the Python debugger locally while running my app in the simulator. But there doesn't seem to be a way to set trust policies, only get them? – Apollo Grace Mar 07 '17 at 19:04
  • And this doesn't work: func forceAllowLocalhost() { var manager = ServerTrustPolicyManager(policies: ["localhost:8443": .disableEvaluation]) Alamofire.ServerTrustPolicyManager = manager } – Apollo Grace Mar 07 '17 at 19:05
  • This doesn't seem to work, it says `Alamofire has no member named Manager` – Matt Jun 19 '17 at 02:49
2

Swift 3 version of @cnoon's code

    manager.delegate.sessionDidReceiveChallenge = { session, challenge in
        var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
        var credential: URLCredential?

        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, let trust = challenge.protectionSpace.serverTrust {
            disposition = URLSession.AuthChallengeDisposition.useCredential
            credential = URLCredential(trust: trust)
        } else {
            if challenge.previousFailureCount > 0 {
                disposition = .cancelAuthenticationChallenge
            } else {
                credential = self.manager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)

                if credential != nil {
                    disposition = .useCredential
                }
            }
        }

        return (disposition, credential)
    }
superarts.org
  • 7,009
  • 1
  • 58
  • 44
1

Swift 3

In my case when I use swagger client library, I changed my code to test the local server like this:

 open func createSessionManager() -> Alamofire.SessionManager {
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = buildHeaders()

    let serverTrustPolicies: [String: ServerTrustPolicy] = ["localhost": .disableEvaluation]

    return Alamofire.SessionManager(configuration: configuration, serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
}
Kiryl Bielašeŭski
  • 2,663
  • 2
  • 28
  • 40
-3

Replacing with https to http of my base url. resolved the error.

Arvind Kumar
  • 2,371
  • 1
  • 18
  • 25