Hi,
I'm using Alamofire for a https connection. I use a nodejs https server. When using curl and providing the CA using --cacert <ca-file>
it works just fine.
However when testing in Alamofire I get this error:
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x60c000047980>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=<CFArray 0x60600015e840 [0x10c05b7b0]>{type = immutable, count = 1, values = (
0 : <cert(0x61600007e680) s: localhost i: localhost>
)}, NSUnderlyingError=0x6040000abe90 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x60c000047980>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=<CFArray 0x60600015e840 [0x10c05b7b0]>{type = immutable, count = 1, values = (
0 : <cert(0x61600007e680) s: localhost i: localhost>
)}}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.
My source looks like this:
class Networking {
static let manager: Manager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"localhost": .DisableEvaluation
]
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
return Alamofire.Manager(configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
}()
func test() {
Networking.manager.request(.GET, "https://localhost:3000/", parameters: nil)
.responseJSON { (response: Response<AnyObject, NSError>) in
// nothing interesting
}
}
I'm using Alamofire from the xcode7.1 branch.
You should just need to include the port number:
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"localhost:3000": .DisableEvaluation
]
If that doesn't work, please add more detail and I'll gladly re-open the issue. 馃憤馃徏
Unfortunately that didn't fix my problem :cry: ... Which detail do you need for investigation?
Could you provide your full curl command? Additionally, would it be possible for us to be able to hit the server to try and debug the issue? I'm wondering if there's some additional challenge we're running into with self-signed certificates.
I set up a test-server at https://api.moritzsternemann.de:3000 (could take a couple of hours for the dns-entry to update :smile:)
curl --cacert root-ca.crt.pem https://api.moritzsternemann.de:3000
works perfectly
I updated the URL and set the serverTrustPolicies like this:
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"api.moritzsternemann.de:3000": .DisableEvaluation,
"api.moritzsternemann.de": .DisableEvaluation
]
BUT now I get an other error:
CFNetwork SSLHandshake failed (-9806)
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9806)
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9806, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x6040000ab4d0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9806, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9806}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., _kCFStreamErrorDomainKey=3}
Thank you for providing all that info and setting up the test server @iMoritz. So much easier to debug the problem on our end. I was able to get to the bottom of your issue. The following test case successfully makes a request to your test server using Alamofire.
func testSelfSignedCertificate() {
// Given
let manager: Alamofire.Manager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"api.moritzsternemann.de": .DisableEvaluation
]
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
return Alamofire.Manager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}()
let expectation = expectationWithDescription("request should succeed")
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: NSError?
// When
manager.request(.GET, "https://api.moritzsternemann.de:3000")
.response { responseRequest, responseResponse, responseData, responseError in
request = responseRequest
response = responseResponse
data = responseData
error = responseError
expectation.fulfill()
}
waitForExpectationsWithTimeout(defaultTimeout, handler: nil)
// Then
XCTAssertNotNil(request, "request should not be nil")
XCTAssertNotNil(response, "response should not be nil")
XCTAssertNotNil(data, "data should not be nil")
XCTAssertNil(error, "error should not be nil")
XCTAssertEqual(response?.statusCode, 200, "response status code should be 200")
}
I was incorrect when I said that the server trust policy should include the port number. It appears with this URL, the challenge host does not include the port number. If you add this test into the Alamofire test suite or into your own test suite, you'll see that it passes successfully.
Test Suite 'Selected tests' started at 2015-10-25 12:57:12.588
Test Suite 'BaseTestCase' started at 2015-10-25 12:57:12.589
Test Case '-[Alamofire_iOS_Tests.BaseTestCase testSelfSignedCertificate]' started.
Test Case '-[Alamofire_iOS_Tests.BaseTestCase testSelfSignedCertificate]' passed (0.460 seconds).
Test Suite 'BaseTestCase' passed at 2015-10-25 12:57:13.050.
Executed 1 test, with 0 failures (0 unexpected) in 0.460 (0.461) seconds
Test Suite 'Selected tests' passed at 2015-10-25 12:57:13.050.
Executed 1 test, with 0 failures (0 unexpected) in 0.460 (0.462) seconds
The key to figuring out what is going on is to add a breakpoint to the ServerTrustPolicyManager.serverTrustPolicyForHost(:)
method. That will allow you to see what the host
is associated with the challenge. There are several other ways to debug this, but that is certainly the easiest.
Hopefully this issue will help others in a similar position. Thanks again for all the info to help us debug! 馃嵒
Hm I tried adding the Test to my projects test suite and it failed...
17:04:45.211 AlamofireTest[19598:801335] _XCT_testBundleReadyWithProtocolVersion:minimumVersion: reply received
17:04:45.214 AlamofireTest[19598:801336] _IDE_startExecutingTestPlanWithProtocolVersion:16
Test Suite 'Selected tests' started at 2015-10-26 17:04:45.218
Test Suite 'AlamofireTestTests' started at 2015-10-26 17:04:45.218
Test Case '-[AlamofireTestTests.AlamofireTestTests testSelfSignedCertificate]' started.
2015-10-26 17:04:45.540 AlamofireTest[19598:801348] CFNetwork SSLHandshake failed (-9806)
2015-10-26 17:04:45.541 AlamofireTest[19598:801348] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9806)
/Users/moritz/Projects/Xcode/AlamofireTest/AlamofireTestTests/AlamofireTestTests.swift:75: error: -[AlamofireTestTests.AlamofireTestTests testSelfSignedCertificate] : XCTAssertNotNil failed - response should not be nil
/Users/moritz/Projects/Xcode/AlamofireTest/AlamofireTestTests/AlamofireTestTests.swift:77: error: -[AlamofireTestTests.AlamofireTestTests testSelfSignedCertificate] : XCTAssertNil failed: "Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9806, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x7fc039900ec0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9806, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9806}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://api.moritzsternemann.de:3000/, NSErrorFailingURLStringKey=https://api.moritzsternemann.de:3000/, _kCFStreamErrorDomainKey=3}" - error should not be nil
/Users/moritz/Projects/Xcode/AlamofireTest/AlamofireTestTests/AlamofireTestTests.swift:78: error: -[AlamofireTestTests.AlamofireTestTests testSelfSignedCertificate] : XCTAssertEqual failed: ("nil") is not equal to ("Optional(200)") - response status code should be 200
Test Case '-[AlamofireTestTests.AlamofireTestTests testSelfSignedCertificate]' failed (0.326 seconds).
Test Suite 'AlamofireTestTests' failed at 2015-10-26 17:04:45.545.
Executed 1 test, with 3 failures (0 unexpected) in 0.326 (0.327) seconds
Test Suite 'Selected tests' failed at 2015-10-26 17:04:45.545.
Executed 1 test, with 3 failures (0 unexpected) in 0.326 (0.328) seconds
Test session log:
/var/folders/xm/j_1zxbhd6qzb7f2bytxkbq6r0000gn/T/com.apple.dt.XCTest-status/Session-2015-10-26_17:04:43-uadmKS.log
Then I tried adding the test to Alamofire's test suite as you mentioned and it passed.
Another interesting thing: I added a breakpoint to ServerTrustPolicyManager.serverTrustPolicyForHost(:)
and it only get's hit when running the test from Alamofire's test suite and not from my apps.
I also tried creating a completely new app for this but I got the same results.
So I thought this could have something to do with my apps target being the iOS simulator and Alamofire's test being run on My Mac. So I created a new Mac Application but testing in it's test suite threw me the same errors.
Maybe you could try this in an iOS App yourself :smile:
Roger...I'll investigate further @iMoritz! Re-opening.
Thanks for all the awesome feedback here. I definitely want to make sure all this is working properly. 馃憤馃徏
I am experiencing similar issues with a self signed certificate. When I add the code @cnoon mentioned earlier to a view controller (commenting out the asserts etc and using debugPrint
statements) it also fails for me:
code:
func testSelfSignedCertificate() {
// Given
let manager: Alamofire.Manager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"api.moritzsternemann.de": .DisableEvaluation
]
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
return Alamofire.Manager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}()
// let expectation = expectationWithDescription("request should succeed")
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: NSError?
// When
manager.request(.GET, "https://api.moritzsternemann.de:3000")
.response { responseRequest, responseResponse, responseData, responseError in
request = responseRequest
response = responseResponse
data = responseData
error = responseError
//expectation.fulfill()
debugPrint(request)
debugPrint(response)
debugPrint(data)
debugPrint(error)
}
// waitForExpectationsWithTimeout(defaultTimeout, handler: nil)
//
// // Then
// XCTAssertNotNil(request, "request should not be nil")
// XCTAssertNotNil(response, "response should not be nil")
// XCTAssertNotNil(data, "data should not be nil")
// XCTAssertNil(error, "error should not be nil")
// XCTAssertEqual(response?.statusCode, 200, "response status code should be 200")
}
output:
Optional(<NSMutableURLRequest: 0x7f8220f8c350> { URL: https://api.moritzsternemann.de:3000 })
nil
Optional(<>)
Optional(Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://api.moritzsternemann.de:3000/, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://api.moritzsternemann.de:3000/})
By the way, I am using Alamofire 3.1.0:
~ $ cat Cartfile.resolved
github "Alamofire/Alamofire" "3.1.0"
github "SwiftyJSON/SwiftyJSON" "2.3.1"
Using curl it works just fine:
~ $ curl --cacert ~/Downloads/api.moritzsternemann.de.cer https://api.moritzsternemann.de:3000
<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>
Thanks for all the info here @iMoritz and @4np. It may take me a couple of days before I can dig into this problem deeply just as a heads up.
Could this issue be related to "App Transport Security"? As it's lower level then NSURLConnection the usual way of using DidReceiveChallenge will not work for self-signed certificates.
Yeah I was thinking that as well so I tried the same code with the NSAppTransportSecurity
/ NSExceptionDomains
(as described here) but no luck.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>moritzsternemann.de</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
<key>NSThirdPartyExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
<key>NSRequiresCertificateTransparency</key>
<false/>
</dict>
</dict>
I am also experiencing issues with some valid SSL certificates, I am not sure if it is related. This code, for example, is also failing for me:
Alamofire.request(.GET, "https://pademo.service-now.com")
.response { response in
debugPrint(response)
}
2015-10-30 17:25:10.117 TestApp[60587:3182750] CFNetwork SSLHandshake failed (-9824)
2015-10-30 17:25:10.118 TestApp[60587:3182750] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
(Optional(<NSMutableURLRequest: 0x7fab6a11da70> { URL: https://pademo.service-now.com }), nil, Optional(<>), Optional(Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9824, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x7fab6a203900 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://pademo.service-now.com/, NSErrorFailingURLStringKey=https://pademo.service-now.com/, _kCFStreamErrorDomainKey=3}))
Even though the certificate if perfectly valid...
Requesting the main site (same certificate issuer) works fine
let request = Alamofire.request(.GET, "https://www.servicenow.com")
.response { response in
debugPrint(response)
}
The main difference being that the pademo
certificate is a wildcard certificate, while the other one is not.
Testing another wildcard certificate (nl.godaddy.com
) however passes and the code runs fine...
Okay, so this was a tricky one to figure out. Long story short, you are both being bit by ATS and need to configure it just right to allow the challenge APIs to be called. Here's an example of the ATS settings you need:
Now I'll dig in here a bit more to try and share what I was able to find out. First off, I can't believe the awful lack of documentation around ATS from Apple. Their original ATS technote has been completely pulled offline. If anyone can find a valid link to the actual Apple docs, PLEASE PROVIDE A LINK!
With that said, I was able to piece this together from a few different links. First off, you should read this entire article. Most of the info you need is in there. This walks through the basics of NSExceptionRequiresForwardSecrecy
and NSExceptionAllowsInsecureHTTPLoads
but doesn't explain them very well at all. I was able to find a bit more info about the cipher relaxation of NSExceptionRequiresForwardSecrecy
here.
From what I can tell, your server must not be using a valid cipher suite, because the request automatically errors out without the NSExceptionRequiresForwardSecrecy
flag set to NO
. Additionally, it appears that the NSExceptionAllowsInsecureHTTPLoads
is a flag to override the entire challenge callback system. If you don't set it to YES
, your challenge will NEVER be called.
Once you get these settings set correctly, then the challenges are called and you can debug whether your server trust policy objects are set up correctly.
I'll be updating the README shortly with this information to make it easier for people to work with self-signed certificates in the future.
Thanks everyone for helping figure this out! 馃嵒
Just want to point out, on El Capitan machines you can use nscurl
command to attempt to diagnose ATS issues.
nscurl --ats-diagnostics https://api.moritzsternemann.de:3000
However, in this instance it wouldn't have helped at all since all of the scenarios it tests for succeed, so it really gives you nothing to go on.
Added ATS section to the README in 55cfc16b.
thanks for the help! @cnoon :+1:
Awesome! :+1: :smile:
Hi, please help me.
I use xcode 7.1, swift 2, Alamofire 3.1.3. When i use curl
curl -H "Accept: application/json" -H -X GET "https://instore.meduzaradio.com/api/station.json" --insecure
{"code":401,"error":"You must be authorized to view this page."}
it works just fine
In xcode i recive error
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9814)
my code:
class HTTPManager: Alamofire.Manager {
static let sharedManager: HTTPManager = {
//let configuration = Timberjack.defaultSessionConfiguration()
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"instore.meduzaradio.com:": .DisableEvaluation
]
var policy: ServerTrustPolicy = ServerTrustPolicy.DisableEvaluation
let manager = HTTPManager(configuration: configuration,serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
return manager
}()
}
class HTTPServise: NSObject {
let baseUrl:String = "https://instore.meduzaradio.com/api/"
var manager: Alamofire.Manager
override init(){
manager = HTTPManager.sharedManager
}
func getRequestWithURL(url:String, parameters:[String: AnyObject]? = nil,completion:(finished: Bool, response: AnyObject?) ->Void ){
abstractRequestWithMethod(.GET, url: url, parameters: parameters, completion: completion)
}
private func abstractRequestWithMethod(method:Alamofire.Method,url:String,parameters:[String: AnyObject]? = nil, completion:(finished: Bool, response: AnyObject?) ->Void ){
manager.request(.GET,(baseUrl+url) as URLStringConvertible)
.responseJSON { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
}
}
Hi @AlexNikov,
Set a breakpoint in the serverTrustPolicyForHost
method in the ServerTrustPolicyManager
class to see if it's getting called. If it is, then you have ATS most likely configured correctly. If it's not getting called, then your ATS configuration is still not correct.
If it is getting called, then check to make sure your host
matches yours exactly. If you still can't get to the bottom of the issue after verifying all this, please open a separate issue with enough info for us to continue to debug the problem. Also please read through all the very detailed info in this post. There's a ton of good info here to help you solve the problem.
Cheers.
Perhaps we could do without self-signed certificates from now on? :)
Read this article on Free HTTPS Certs for all
Couldn't agree more @4np! 馃帀
I'm working on OSX 10.11 and was facing this issue, the following is for reference. The Info.plist App Transport Security Settings
is not enough on its own, it rarely works. The certificate should be added to the Keychain and marked a trusted, this would resolve the issue of self-signed certificates in the development environment without adding the risk of forgetting the Info.plist settings set in a production release.
That should not actually be true @Link-. You should certainly be able to disable evaluation without having to mark the self-signed cert as a trusted cert. Can anyone else out there confirm this? We have many tests verifying this behavior, but none that deal with ATS at an app level.
@cnoon the problem best represents itself when dealing with localhost self-signed certs.
If NSAppTransportSecurity does not work, try the following along with it:
Here is a possible solution on how to accept invalid SSL Certificates in Alamofire.
Add the following function in your AppDelegate class and call it in didFinishLaunching function:
func acceptInvalidSSLCerts()
{
let manager = Alamofire.Manager.sharedInstance
print("trying to accept invalid certs")
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
print("received challenge")
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)
}
}
Reference:-> Accepting invalid SSL certificates in Alamofire
I would NEVER recommend doing the above in production @tvich1! For everyone thinking this is a good solution, I can't stress enough that you should never actually do this. Instead, use something like Let's Encrypt to generate a valid cert.
Apple said they will require ATS in all apps by January 1, 2017. Are there other options to keep custom CA working?
@tvich1 I have done exactly what you suggested in your post. I then try to make the following request in a view controller:
` let userPasswordString: String = "---:---"
let authData = userPasswordString.dataUsingEncoding(NSUTF8StringEncoding)
let base64EncodedCredentials = authData!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions([]))
let headers = ["Authorization": "Basic (base64EncodedCredentials)"]
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"---.com": .DisableEvaluation,
]
let manager = Alamofire.Manager(
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
manager.request(.GET, "https://---.com:7183/api/v10/clusters/cluster/services", headers: headers)
.responseJSON { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}`
However, I am getting the following output.
trying to accept invalid certs
User Authenticated
Optional(<NSMutableURLRequest: 0x7f9ac16d6b80> { URL: https://---.com:7183/api/v10/clusters/cluster/services })
nil
Optional(<>)
FAILURE
Note, I have replaced some of the text with "---" for security reasons. I have asked the api team that I am using to create a public certificate, but is there any workaround that I can do for now? @cnoon
@tvich1 @cnoon Nevermind... I was able to solve this problem by adding the acceptInvalidSSLCerts() to my view controller class and making the Alamo.manager variable a class variable.
Ah. So your Manager
instance was being deallocated in the middle of the inflight request @emilynswanson?
@cnoon How to set value for Exception Domains
in ATS
for dynamic hostnames ?
Hi,
I'm using Alamofire for a https connection.
However when testing in Alamofire I get this error:
URLError occurred: URLError(_nsError: Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://192.168.X.XX/VMSSite/Handlers/Common/iOSServer.ashx?RegID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://192.168.X.XX/VMSSite/Handlers/Common/iOSServer.ashx?RegID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX})
status code: nil
My source looks like this:
`var defaultManager = Alamofire.SessionManager.default
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"192.168.X.XX:443": .disableEvaluation,
"192.168.X.XX": .disableEvaluation
]
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30 //seconds
configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
//defaultManager = SessionManager(configuration: configuration, delegate: SessionDelegate(), serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
defaultManager = SessionManager(configuration: configuration, serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
defaultManager.request("https://192.168.X.XX/VMSSite/Handlers/Common/iOSServer.ashx?RegID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", method: .post, parameters: nil, encoding: JSONEncoding.default).responseJSON { response in
debugPrint(response)
//Ref link - http://stackoverflow.com/questions/29131253/swift-alamofire-how-to-get-the-http-response-status-code
var statusCode = response.response?.statusCode
if let error = response.result.error as? AFError {
statusCode = error._code // statusCode private
switch error {
case .invalidURL(let url):
print("Invalid URL: \(url) - \(error.localizedDescription)")
case .parameterEncodingFailed(let reason):
print("Parameter encoding failed: \(error.localizedDescription)")
print("Failure Reason: \(reason)")
case .multipartEncodingFailed(let reason):
print("Multipart encoding failed: \(error.localizedDescription)")
print("Failure Reason: \(reason)")
case .responseValidationFailed(let reason):
print("Response validation failed: \(error.localizedDescription)")
print("Failure Reason: \(reason)")
switch reason {
case .dataFileNil, .dataFileReadFailed:
print("Downloaded file could not be read")
case .missingContentType(let acceptableContentTypes):
print("Content Type Missing: \(acceptableContentTypes)")
case .unacceptableContentType(let acceptableContentTypes, let responseContentType):
print("Response content type: \(responseContentType) was unacceptable: \(acceptableContentTypes)")
case .unacceptableStatusCode(let code):
print("Response status code was unacceptable: \(code)")
statusCode = code
}
case .responseSerializationFailed(let reason):
print("Response serialization failed: \(error.localizedDescription)")
print("Failure Reason: \(reason)")
// statusCode = 3840 ???? maybe..
}
print("Underlying error: \(error.underlyingError)")
} else if let error = response.result.error as? URLError {
print("URLError occurred: \(error)")
} else {
print("Unknown error: \(response.result.error)")
}
print("status code: \(statusCode)") // the status code
`
I'm using Swift 3 and Alamofire 4.0 from the xcode8.1 branch.
Please help me.
And
How to set value for Exception Domains in ATS for dynamic hostnames?
"Cancelled" error is due to concurrent requests, previous request fails with "cancelled" error when you use the same Manager.
I handled this by not sending any request until authorization request is either failure/success.
hi stephen,
Thanks for reply.
can you explain this with code.
Hi @tejasverixo, make sure you're defaultManager
instance is not being released. Other than that, please file a question on Stack Overflow. We use our GitHub project for bug reports and feature requests.
Hi,
I tried some variant code above, but I still get error
FAILURE: Error Domain=NSURLErrorDomain Code=-999 "cancelled"
btw, I use IP Address instead domain for my URL request and my server is detected as not secure
I'm using Alamofire 4.2
I am going to make the following query. For reasons of outdated libraries, I had to switch to Alamofire version (~> 5.0). Well, that change affected the entire logic of the project, which I am trying to adapt ... and above all I found this problem ... I found several reports related to the subject. But I can't find the proper way to adapt this logic. Recommendations on how to adapt it?
func acceptInvalidSSLCerts() {
let manager = AF
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
var credential: URLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
disposition = .useCredential
credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
} 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)
}
}
@IrwinBravoOporto Please don't post on old issues. If you have a question, we have several avenues of support, as well as our Security documentation.
@IrwinBravoOporto No publiques temas antiguos. Si tiene alguna pregunta, tenemos varias v铆as de soporte, as铆 como nuestra documentaci贸n de seguridad .
It is not an old theme, currently this code is deprecated and requires an update in swift 5.
Most helpful comment
If NSAppTransportSecurity does not work, try the following along with it:
Here is a possible solution on how to accept invalid SSL Certificates in Alamofire.
Add the following function in your AppDelegate class and call it in didFinishLaunching function:
Reference:-> Accepting invalid SSL certificates in Alamofire