Why Is a Https Nsurlsession Connection Only Challenged Once Per Domain

Why is a HTTPS NSURLSession connection only challenged once per domain?

What you're really trying to do here is evaluate the trust of the server's credentials for each request.

Technote 2232: HTTPS Server Trust Evaluation describes HTTP trust evaluation at a high level, and goes into more detail about implementing it.

When you connect to a host using SSL/TLS, the host presents a set of cryptographic credentials. Your application (and potentially the user directly) must evaluate those credentials and decide if the can be trusted.

This is like looking at someone's driver's license or passport, and deciding wether they are who they say they are.

Imagine if you looked at someone's identification once for each word they speak. That would get tedius! It would not make sense unless the person changed, or their identification changed. iOS will perform trust evaluation if the server or it's credentials change.

This actually happens at the transport (socket) layer underneath HTTP, but Foundation thankfully exposes this higher up in APIs such as NSURLConnection and NSURLSession as a credential challenge for a given protection space. If the protection space (the host) or the server credentials change, a new credential challenge occurs. This will in turn prompt trust evaluation.

Since SSL/TLS is a socket-level security measure, the real work happens far below the Foundation URL loading system inside SecureTransport, the secure socket framework. SecureTransport maintains its own per-process TLS session cache. This is the layer you would have to circumvent to get the behavior you are looking for - you would need to clear the TLS session cache for each connection, or force SecureTransport to disregard the session cache for your process.

Technical Q&A 1727: TLS Session Cache describes the SecureTransport session cache in more detail, and may provide some interesting options for circumventing the TLS cache (i.e. messing with DNS).

At this time there is no API for clearing or modifying the SecureTransport TLS session cache. You can file a radar requesting this functionality.

TL;DR;

"So how come the challenge is only made once?"
The result of the first TLS trust evaluation is cached by SecureTransport in the session cache.

There is not a way to control that particular behavior at this time.

You can try using some other HTTPS library or framework (such as OpenSSL), YMMV.

IOS9 SSL error with NSURLSession

After some discussion with Apple Support, the issue is due to the self signed certificate.

ATS trusts only certificate signed by a well known CA, all others are rejected. As a consequence the only solution with a Self signed certificate is to set an exception with NSExceptionDomains.

Swift 3 NSURLSession/NSURLConnection HTTP load failed when connecting to a site with authentication

Okay well I didn't know how to fix this but I discovered that Alamofire can be used to do what I needed. This is a local project for inventory management so I wasn't concerned about the security of bypassing the certificates. My code is here:

       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 = Manager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)

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

return (disposition, credential)
}

private var Manager: Alamofire.SessionManager = {

// Create the server trust policies
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"https://SERVER:PORT": .disableEvaluation
]

// Create custom manager
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
let manager = Alamofire.SessionManager(
configuration: URLSessionConfiguration.default,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
let sessionManager = SessionManager(
serverTrustPolicyManager: ServerTrustPolicyManager(
policies: ["https://SERVER:PORT": .disableEvaluation]
)
)
return manager
}()

open class MyServerTrustPolicyManager: ServerTrustPolicyManager {

// Override this function in order to trust any self-signed https
open override func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? {
return ServerTrustPolicy.disableEvaluation
}

}

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802) on a subdomain?

App Transport Security is not just HTTP vs HTTPS. You need to be using properly configured servers+certificates to avoid an ATS issue. From the Apple docs [1]:

The server must support at least Transport Layer Security (TLS)
protocol version 1.2. Connection ciphers are limited to those that
provide forward secrecy. Certificates must be signed using a SHA256 or
greater signature hash algorithm, with either a 2048 bit or greater
RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid
certificates result in a hard failure and no connection.

If you're on OS X 10.11 (or later), you can use nscurl to troubleshoot. Pop open a terminal and run this:

/usr/bin/nscurl --ats-diagnostics https://staging.ourdomain.com

[1] https://developer.apple.com/library/ios/technotes/App-Transport-Security-Technote/index.html



Related Topics



Leave a reply



Submit