Faiz Mokhtar Faiz Mokhtar - 3 months ago 51
Swift Question

Bypassing App Transport Security to allow unsecured HTTP server

Situation:



I have to connect to these two different servers for development and staging use. Both of the servers have unstrusted SSL certificates.
For example purposes, these two servers URL's are:

Staging server:
https://52.70.13.2:1010/


Development server:
https://example.entrydns.org:1012


Whenever I tried to call the API, i get empty response with following error:

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


or sometimes,

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)


I use Moya for my network layers, which is basically just a nice wrapper for Alamofire. For additional info, I use
XCode 7.3
and the app only supports
> iOS 9
.

What I've did:



I am very well aware of App Transport Security issue that Apple want to enforce. I wanted to disable it for development but still in vain. Some of the ways I tried to bypass the ATS it are as the following:


  1. Add the following in my
    plist
    to allow arbitrary loads.

    <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    </dict>

  2. Explicitly defines the domain exceptions.

    <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSExceptionDomains</key>
    <dict>
    <key>example.entrydns.org</key>
    <dict>
    <key>NSIncludesSubdomains</key>
    <true/>
    <key>NSExceptionAllowsInsecureHTTPLoads</key>
    <true/>
    <key>NSExceptionRequiresForwardSecrecy</key>
    <true/>
    <key>NSExceptionMinimumTLSVersion</key>
    <string>TLSv1.1</string>
    <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
    <false/>
    <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
    <true/>
    <key>NSThirdPartyExceptionMinimumTLSVersion</key>
    <string>TLSv1.1</string>
    <key>NSRequiresCertificateTransparency</key>
    <false/>
    </dict>
    </dict>
    </dict>



Here's the screenshot for my
plist
:
enter image description here


  1. I also tried to disable the Server Trust Policy of Alamofire manager shared instance. Here's the example code:

    // Disable Policies
    let policies: [String: ServerTrustPolicy] = [
    "https://example.entrydns.org:1012/": .DisableEvaluation,
    "https://52.70.13.2:1010/": .DisableEvaluation
    ]

    let manager = Manager(
    configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
    serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies)
    )
    // ---------------
    let networkLogger = NetworkLoggerPlugin(verbose: true, responseDataFormatter: nil)

    let endpointClosure = { (target: ExampleAPI) -> Endpoint<ExampleAPI> in
    let url = target.baseURL.URLByAppendingPathComponent(target.path).absoluteString
    let endpoint: Endpoint<ExampleAPI> = Endpoint<ExampleAPI>
    (URL: url,
    sampleResponseClosure: {.NetworkResponse(200, target.sampleData)},
    method: target.method,
    parameters: target.parameters,
    parameterEncoding: .URLEncodedInURL)
    return endpoint.endpointByAddingHTTPHeaderFields(target.header())
    }

    let ExampleProvider = MoyaProvider<ExampleAPI>(manager: manager,
    plugins:[networkLogger],
    endpointClosure: endpointClosure)

  2. Open the URLs and download the certs on my device and simulators.



Even after all the steps above I still got the same error. Any takes on what I did wrong and what I can do to solve this problem? BTW, it would be great if I can avoid server-side solution.

Thanks in advance.

References:




Answer

Define your policies with just the hostname.

// Disable Policies
let policies: [String: ServerTrustPolicy] = [
    "example.entrydns.org": .DisableEvaluation
]