0

I have a HTTP REST server with a self-signed certificate. I want to talk to this server from an iOS Swift app, using alamofire. The current code that I have is:

```

let Almgr : Alamofire.SessionManager = {
    // Create the server trust policies
    let serverTrustPolicies: [String: ServerTrustPolicy] = [
        "localhost": .disableEvaluation
    ]
    // Create custom manager
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
    let man = Alamofire.SessionManager(
        configuration: URLSessionConfiguration.default,
        serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )
    return man
}()

 Almgr.request(url, method: .post, parameters: params).responseJSON {
            response in

            if response.result.isSuccess {
                print("Success")
            } else {
                print("Failure")
            }
        }

With the above code snippet, I am always getting an error when I try to make the http call Almgr.request. The error message is:

2017-12-30 18:24:20.114486+0530 myApp[58036:2721102] ATS failed system trust
2017-12-30 18:24:20.114625+0530 myApp[58036:2721102] System Trust failed for [1:0x600000178a80]
2017-12-30 18:24:20.114814+0530 myApp[58036:2721102] TIC SSL Trust Error [1:0x600000178a80]: 3:0
2017-12-30 18:24:20.115142+0530 myApp[58036:2721102] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
2017-12-30 18:24:20.115274+0530 myApp[58036:2721102] Task <4E3D9E88-B9CE-48C4-850C-5A3E7C9A6A72>.<1> HTTP load failed (error code: -1200 [3:-9802])
2017-12-30 18:24:20.115469+0530 myApp[58036:2721231] Task <4E3D9E88-B9CE-48C4-850C-5A3E7C9A6A72>.<1> finished with error - code: -1200

Any idea how to get this fixed ? I do not want any checks to be done if the url is localhost on port 8000. I have even tried with adding port to the serverTrustPolicies definition but that does not make any difference and I still get error. Any help ?

Update: My problem I believe is related to https://developer.apple.com/library/content/qa/qa1948/_index.html but not found the way to fix yet.

Sankar
  • 6,192
  • 12
  • 65
  • 89

3 Answers3

1

1.

Your approach of modifying server trust policies should work when providing the port. Also see this post. Maybe you are testing your app with the simulator and trying to connect to a web server on the same machine? This can cause all kinds of connection problems (or why are you trying to connect to localhost anyway?).

2.

You should never set NSAllowsLocalNetworking or similar parameters. It breaks SSL and you never know what may happen, even in the local network. If absolutely necessary, you should just make exceptions for single hosts and ports as stated above.

3.

You should never use self signed certificates because this also breaks SSL. It is very easy to obtain a valid certificate using Let's Encrypt. Though, in some cases it is just not possible to obtain a valid certificate. You should then create your own certificate authority and export the CA root certificate to your device. This way, you also make an exception for only one specific host.

Please note that security is crucial in all applications. Please only make exceptions if you exactly know what you are doing.

sundance
  • 2,930
  • 1
  • 20
  • 25
  • >1 That does not work anymore (with swift 4.0 and Mac OS 10.13.2 atleast). This is for my local development and not production. >2 Setting NSAllowsLocalNetworking relaxes SSL strictness only for local host access and not any other server. >3 I cannot get a certificate for localhost with letsencrypt, can I ? Creating a new CA will be too complex if I just want to focus on local development in my laptop. Are there any potential vulnerabilities that I am missing by setting the NSAllowsLocalNetworking ? I am not able to find any such by reading that docs. Do I miss something ? Thanks. – Sankar Jan 02 '18 at 04:23
  • 1.: Did you try using the IP address instead of "localhost"? Did you try using an external device instead of the simulator? – sundance Jan 02 '18 at 09:56
  • 2: Network communication without encryption should be avoided in all cases. 3: You need a static IP address for a valid certificate. – sundance Jan 02 '18 at 10:06
0

I have figured out the solution. We need to edit the Info.plist file and add the following section:

<key>NSAppTransportSecurity</key>
<dict>
        <key>NSAllowsLocalNetworking</key>
        <true/>
</dict>

to let iOS allow local networking without https errors.

Sankar
  • 6,192
  • 12
  • 65
  • 89
0

I was facing same problems. What I figured out and what works:

let almgr:Alamofire.SessionManager = {
    //getcertificates is my own method where i create certificate with data from my .cer file
    let certificates = getCertificates()
    let trustPolicy = ServerTrustPolicy.pinCertificates(certificates: certificates, validateCertificateChain: true, validateHost: true)

// Here was the problem. I had to modify that dict: (localhost with port and with .disableEvaluation)
    let serverTrustPolicies = ["liper:8000":trustPolicy, "liper":.disableEvaluation]
    let serverTrustPolicyManager = ServerTrustPolicyManager(policies: serverTrustPolicies)

    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
    let man = Alamofire.SessionManager(configuration: URLSessionConfiguration.default, serverTrustPolicyManager: serverTrustPolicyManager)
    return man
}()
M. Wojcik
  • 2,301
  • 3
  • 23
  • 31