Self-signed certificate iOS - ios

I am trying to configure my iOS app to accept self-signed certificates.
I am trying to fetch the data on a button click. Below is the code that I am using currently:
private var manager : SessionManager?
func setManager(url: String) {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
url: .disableEvaluation
]
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
manager = Alamofire.SessionManager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}
#IBAction func nonCertifiedClick(_ sender: UIButton) {
outputText.text = ""
setManager(url: "sand.xxx.int:16443")
manager?.request("https://sand.xxx.int:16443/version").response { response in
debugPrint("R: \(response)")
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)")
self.outputText.text = utf8Text
}
}
}
My Info.plist file has the below configuration:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
But when the request is executed, I get the following response:
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
"R: DefaultDataResponse(request: Optional(https://sand.xxx.int:16443/version), response: nil, data: Optional(0 bytes),
error: 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 “sand.xxx.int” which could put your confidential information at risk.\"
UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x600000105730>,
NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?,
_kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813,
NSErrorPeerCertificateChainKey=(\n \"<cert(0x7fcf8b81e800) s: sand i: sand>\"\n),
NSUnderlyingError=0x60000005f440 {Error Domain=kCFErrorDomainCFNetwork Code=-1202 \"(null)\" UserInfo={_kCFStreamPropertySSLClientCertificateState=0,
kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x600000105730>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9813,
_kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813,
kCFStreamPropertySSLPeerCertificates=(\n \"<cert(0x7fcf8b81e800) s: sand i: sand>\"\n)}},
NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “sand.xxx.int” which could put your confidential information at risk.,
NSErrorFailingURLKey=https://sand.xxx.int:16443/version,
NSErrorFailingURLStringKey=https://sand.xxx.int:16443/version, NSErrorClientCertificateStateKey=0}),
_metrics: Optional((Task Interval) <_NSConcreteDateInterval: 0x600000224e40> (Start Date) 2016-11-02 14:13:57 +0000 + (Duration) 0.381569 seconds = (End Date) 2016-11-02 14:13:58 +0000\n(Redirect Count) 0\n(Transaction Metrics) (Request) <NSURLRequest: 0x600000200120> { URL: https://sand.xxx.int:16443/version }\n(Response) (null)\n(Fetch Start) 2016-11-02 14:13:57 +0000\n(Domain Lookup Start) (null)\n(Domain Lookup End) (null)\n(Connect Start) (null)\n(Secure Connection Start) (null)\n(Secure Connection End) (null)\n(Connect End) (null)\n(Request Start) 2016-11-02 14:13:57 +0000\n(Request End) 2016-11-02 14:13:57 +0000\n(Response Start) 2016-11-02 14:13:57 +0000\n(Response End) (null)\n(Protocol Name) (null)\n(Proxy Connection) NO\n(Reused Connection) YES\n(Fetch Type) Unknown\n\n))"
Data:
I am testing this on Xcode 8.1 with Swift3 and Alamofire4.
What am I misisng here to make it work right?
Update (Answer)
If incase someone encounters the same issue, the problem was the server's SSL certificate. The certificate needs to be signed with at least SHA256 algorithm but mine was signed with SHA1.

I faced the same problem. But using your question, i found the solution. Tnx..
Here is my solution. it works with swift 3
create a class SecurityCertificateManager
import Foundation
import Alamofire
class SecurityCertificateManager {
static let sharedInstance = SecurityCertificateManager()
let defaultManager: Alamofire.SessionManager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"272.73.41.156": .disableEvaluation
]
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
return Alamofire.SessionManager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}()
}
call it like this in viewDIdLoad
let baseUrl ="https://272.73.41.156/cas/tickets?"+"username="+userEmail.text!+"&password="+userPassword.text!
print("Base url : \(baseUrl)")
let params2 = ["nostring": "nodata", "nostring": "nodata",]
SecurityCertificateManager.sharedInstance.defaultManager.request(baseUrl, method: .post, parameters: params2, encoding: JSONEncoding.default, headers: ["Content-Type":"application/x-www-form-urlencoded"]).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
if response.result.value != nil{
print("response : \(response.result.value)")
}
break
case .failure(_):
print("Failure : \(response.result.error)")
break
}
}
It Works in Swift3

Related

The network connection is lost only in iOS 13.1.3 (Alamofire)

My app connects to a localhost API through Alamofire. I have implemented URL Scheme, so when I click the link from iMessage it opens my app and in viewDidLoad() it connects to the API. For some reason I am getting following error only in iOS 13.1.3 but it is working smoothly in iOS 12.4. All I am testing in real devices.
Error:
2019-10-21 10:32:13.059194+0530 TestAPI[882:164673] [] nw_read_request_report [C5] Receive failed with error "Software caused connection abort"
2019-10-21 10:32:13.060020+0530 TestAPI[882:164673] Task <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4> HTTP load failed, 363/0 bytes (error code: -1005 [4:-4])
2019-10-21 10:32:13.076737+0530 TestAPI[882:164603] Task <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4> finished with error [-1005] Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x283d13840 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x2810a9a40 [0x1d42775e0]>{length = 16, capacity = 16, bytes = 0x100293ddc0a808680000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=http://192.168.8.104:37853/auth/test, NSErrorFailingURLKey=http://192.168.8.104:37853/auth/test, _kCFStreamErrorDomainKey=4}
2019-10-21 10:32:13.590311+0530 TestAPI[882:164306] FBSDKLog: Missing [FBSDKAppEvents appID] for [FBSDKAppEvents publishInstall:]
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x283d13840 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x2810a9a40 [0x1d42775e0]>{length = 16, capacity = 16, bytes = 0x100293ddc0a808680000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=http://192.168.8.104:37853/auth/test, NSErrorFailingURLKey=http://192.168.8.104:37853/auth/test, _kCFStreamErrorDomainKey=4}
Here is the Code:
override func viewDidLoad()
{
super.viewDidLoad()
txtLable.text = "test"
let testServices = TestService()
let test: Parameters = [
"test": "test"
]
testServices.TestNonSecureConnection(parameters: test, completionHandler: {(returnUserVerificationStatus) -> Void in
if(returnUserVerificationStatus != "failed")
{
self.txtLable.text = returnUserVerificationStatus
}else{
print("failed")
}
})
}
class TestService
{
func TestNonSecureConnection(parameters: Parameters, completionHandler: #escaping (_ returnUserVerificationStatus: String)-> Void )
{
var headers: HTTPHeaders = [:]
var resultString = ""
let url = URL(string: Config.LOGIN_SERVER_URL + "/auth/test")!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
do {
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
} catch {
// No-op
}
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
Alamofire.request(urlRequest)
.responseString() { response in
switch response.result {
case .success:
resultString = response.result.value!
completionHandler(resultString)
case .failure(let error):
print(error)
}
}
}
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
self.scheme = url.scheme
self.path = url.path
self.query = url.query
let viewController = storyBoard.instantiateViewController(withIdentifier: "viewcontroller") as! ViewController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
return true
}
Essentially, the underlying NSURLRequest is trying to re-use an HTTP connection that has been dropped by the server. This is apparently caused because the client libraries and your server expect different lifespans for the connection. Or something. Honestly, I'm not 100% sure on the why, but the solutions below all suggest that's what is happening.
There are 3 different ways to solve this one:
Disable KeepAlive on your server
This will cause new connections to be re-created for each new request. Depending on the pattern in which you talk to the server
this may be inconsequential ... or it may be performance concern.
Leave KeepAlive ON but make KeepAliveTimeout longer than 30s
This is
the opposite tradeoff as #1. It will be faster and if you're hitting
the server a lot you may notice it.
This will however cause your server to build up connections and reduce the number of concurrent users you can support. The performance impact of either choice
depends somewhat on what server you're running and you should be
able to decide with a little googling around for "KeepAlive best
practices".
Detect the error code and immediately retry the same query.
When you receive this error - check the error code and immediately retry the
same request. If the error is caused by using a defunct connection, the new query will create a new connection automagically and should work. If the network is genuinely gone the you've got bigger problems.
It's possible that this error will come from other sources, but I've tried all 3 of these approaches and each one solved the issue (obviously with different tradeoffs).
refer to : this post

Alamofire post method in iOS Swift 4?

For getting push notification here i am sending postitem, token, like count and currentname using alamofire post method(pod version alamofire 4.5). I did not get any response when post method called and it does not show any errors.
I tried keeping breaking points in alamofire function, it call alamofire.requestion then it goes out function.
Here is the code tried to send post method to backend:
func postNotification(postItem: String, post: Post) {
print("Get token from post:::",post.token)
print(postItem)
let token = UserDefaults.standard.string(forKey: "token")
let headers: HTTPHeaders = ["Content-Type" :"application/x-www-form-urlencoded"]
let parameters : [String:Any] = ["count":post.likeCount!, "likedby":currentName, "postId=":postItem, "token": post.token!]
Alamofire.request("http://highavenue.co:9000/likesnotification/", method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
if let data = response.result.value{
print(data)
}
break
case .failure(_):
print(response.result.error as Any)
break
}
}
}
Getting console error like this
2018-07-10 14:21:07.980212+0530 HighAvenue[10584:4236493] Task <B5FC98AB-C3FE-
4D4F-9A93-72D3FFE35DF7>.<1> finished with error - code: -1001
Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."
UserInfo={NSUnderlyingError=0x1c0e478f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=http://highavenue.co:9000/likesnotification/, NSErrorFailingURLKey=http://highavenue.co:9000/likesnotification/, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.})
That is because you are not setting request time in your network call, by default your request time is a small interval, so please increase request timeout time. something like this,
let request = NSMutableURLRequest(url: URL(string: "")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.timeoutInterval = 120 // 120 secs
let values = ["key": "value"]
request.httpBody = try! JSONSerialization.data(withJSONObject: values, options: [])
Alamofire.request(request as! URLRequestConvertible).responseJSON {
response in
// do whatever you want here
}
Second mistake in your code is you are trying to access http url which are by default are not allowed so you have to by pass this security from your app, Please refer to this answer in order to remove this security layer from your app.
The resource could not be loaded because the App Transport Security policy requires the use of a secure connection

Can not fetch data using Alamofire?

I am trying to fetch data in my iOS app from my Django backend. In postman if I perform a GET request on the following URL http://127.0.0.1:8000/api/places/categories with the params being Key:"Authorization" Value: "Bearer access_token".I get a JSON response.
Inside my app I am doing something like this with the help of Alamofire:
let access_token = "123"
let headers = ["Authorization": "Bearer" + access_token]
Alamofire.request(self.categoriesUrl, method: .get, parameters:nil,encoding: JSONEncoding.default,headers: headers).response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.error)")
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)")
}
}
I get an error saying Authorization Credentials were not provided. I understand this and it asks me to pass in the parameters but the parameters just need a token. So I do something like this:
let access_token = "123"
let params = ["Authorization": "Bearer" + access_token]
Alamofire.request(self.categoriesUrl, method: .get, parameters:params,encoding: JSONEncoding.default,headers: nil).response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.error)")
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)")
}
}
It waits for a while but fails to fetch the data with the following error:
Response: nil
Error: Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x61800004b0d0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=http://127.0.0.1:8000/api/places/categories/, NSErrorFailingURLKey=http://127.0.0.1:8000/api/places/categories/, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.})
Data:
EDIT1:
This is very simple to fix, I guess you are using iOS10 or later version of OS. So instead of calling http , just call https, which means the API calling protocol has been changed to http to https in iOS10 and later.
You have a typo here :
let params = ["Authorization": "Bearer" + access_token]
You're missing a space after Bearer.

Swift 3 How to validate server certificate using SSL Pinning and AlamoFire?

I'm writing an app in swift 3 that needs to talk to my server. I have the full certificate chain in der and crt format which I am the CA for(Not to be confused with self signed). How do I use this in my app to validate my server? Below is my rest call and response
Rest Call:
var request = URLRequest(url: URL(string: "https://myserver/login")!)
request.addValue("Content-Type", forHTTPHeaderField: "application/json")
request.httpMethod = "GET"
let session = URLSession.shared
session.dataTask(with: request) {data, response, err in
print("=========================DATA===============================")
if data != nil {
print(data!)
}
print("=========================RESPONSE===============================")
if response != nil {
print(response!)
}
print("=========================ERR===============================")
if err != nil {
print(err!)
}
}.resume()
Output:
=========================DATA===============================
=========================RESPONSE===============================
=========================ERR===============================
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x60800011f020>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
"<cert(0x7fae4803d200) s: myserver i: MySubCA>",
"<cert(0x7fae48047000) s: MySubCA i: MyRootCA>",
"<cert(0x7fae48044600) s: MyRootCA i: MyRootCA>"
), NSUnderlyingError=0x60800005a040 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x60800011f020>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x7fae4803d200) s: myserver i: MySubCA>",
"<cert(0x7fae48047000) s: MySubCA i: MyRootCA>",
"<cert(0x7fae48044600) s: MyRootCA i: MyRootCA>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://myserver/login, NSErrorFailingURLStringKey=https://myserver/login, NSErrorClientCertificateStateKey=0}
I solved it pretty simply leveraging an online blog, AlamoFire and openssl.
I used AlamoFire for the networking on iOS.
I used an article about SSL pinning on iOS to get on the right direction.
I used openssl to convert my cert to der format.
Der conversion through openssl.
openssl x509 -in cert.crt -out cert.der -outform DER
You will need to add the der formatted cert to your app bundle.
Swift 3 implementation
// Your hostname and endpoint
let hostname = "YOUR_HOST_NAME"
let endpoint = "YOUR_ENDPOINT"
let cert = "YOUR_CERT" // e.g. for cert.der, this should just be "cert"
// Set up certificates
let pathToCert = Bundle.main.path(forResource: cert, ofType: "der")
let localCertificate = NSData(contentsOfFile: pathToCert!)
let certificates = [SecCertificateCreateWithData(nil, localCertificate!)!]
// Configure the trust policy manager
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: true
)
let serverTrustPolicies = [hostname: serverTrustPolicy]
let serverTrustPolicyManager = ServerTrustPolicyManager(policies: serverTrustPolicies)
// Configure session manager with trust policy
afManager = SessionManager(
configuration: URLSessionConfiguration.default,
serverTrustPolicyManager: serverTrustPolicyManager
)
afManager.request(endpoint, method: .get).responseJSON { response in
debugPrint("All Response Info: \(response)")
}

Alamofire with a self-signed certificate / ServerTrustPolicy

I want to use Alamofire to communicate with my server over a https connection with a self signed certificate. My environment runs on localhost. I've tried to connect, but the response all the time looks like this:
Success: false
Response String: nil
I've done it with the following code:
import Foundation
import UIKit
import Alamofire
class MessageView: UITableViewController {
let defaultManager: Alamofire.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)
)
}()
override func viewDidLoad() {
super.viewDidLoad()
defaultManager
.request(.GET, "https://localhost:3443/message")
.responseJSON { _, _, result in
print("Success: \(result.isSuccess)")
print("Response String: \(result.value)")
}
}
}
I've created the server side certificates with this line of bash:
openssl req -x509 -nodes -days 999 -newkey rsa:2048 -keyout server.key -out server.crt
I don't know what am I doing wrong. Help would be great.
### Update ###
Here is the cURL request. In my opinion, there is no problem, or am I wrong?
curl -X GET https://localhost:3443/message -k -v
* Trying ::1...
* Connected to localhost (::1) port 3443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
* Server certificate: teawithfruit
> GET /message HTTP/1.1
> Host: localhost:3443
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Content-Length: 1073
< Date: Tue, 15 Sep 2015 06:20:45 GMT
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
[{"_id":"55f3ed2d81a334558241e2f4","email":"abc#def.com","password":"abc","name":"teawithfruit","language":"en","__v":0,"timestamp":1442049325159,"messages":[{"_id":"55f40553e568236589772c61","user":"55f3ed2d81a334558241e2f4","language":"en","message":"hello world","__v":0,"timestamp":1442055507301,"id":"55f40553e568236589772c61"},{"_id":"55f48b2b02e7b059b54e99f6","user":"55f3ed2d81a334558241e2f4","language":"en","message":"hello world","__v":0,"timestamp":1442089771312,"id":"55f48b2b02e7b059b54e99f6"}],"id":"55f3ed2d81a334558241e2f4"}]
### Update 2 ###
Sorry for the late answer.
Here are the two debugPrints:
Request debugPrint:
$ curl -i \
-H "Accept-Language: en-US;q=1.0" \
-H "Accept-Encoding: gzip;q=1.0,compress;q=0.5" \
-H "User-Agent: Message/com.teawithfruit.Message (1; OS Version 9.0 (Build 13A340))" \
"https://localhost:3443/message"
Result debugPrint:
FAILURE: Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://localhost:3443/message, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://localhost:3443/message}
### Update 3 ###
Here is the complete error with maybe an ATS problem?
nil
$ curl -i \
-H "Accept-Language: en-US;q=1.0" \
-H "Accept-Encoding: gzip;q=1.0,compress;q=0.5" \
-H "User-Agent: Message/com.teawithfruit.Message (1; OS Version 9.0 (Build 13A340))" \
"https://localhost:3443/message"
2015-10-17 15:10:48.346 Message[25531:1001269] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
FAILURE: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x7fdc3044b740>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=<CFArray 0x7fdc2a7ca300 [0x10f7037b0]>{type = immutable, count = 1, values = (
0 : <cert(0x7fdc31d31670) s: teawithfruit i: teawithfruit>
)}, NSUnderlyingError=0x7fdc30064bd0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x7fdc3044b740>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=<CFArray 0x7fdc2a7ca300 [0x10f7037b0]>{type = immutable, count = 1, values = (
0 : <cert(0x7fdc31d31670) s: teawithfruit i: teawithfruit>
)}}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://localhost:3443/message, NSErrorFailingURLStringKey=https://localhost:3443/message, NSErrorClientCertificateStateKey=0}
Success: false
Response String: nil
You need to add the port domain when you create your ServerTrustPolicy dictionary.
let defaultManager: Alamofire.Manager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"localhost:3443": .DisableEvaluation
]
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
return Alamofire.Manager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}()
For swift 4:
private static var Manager : Alamofire.SessionManager = {
// Create the server trust policies
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"your domain goes here": .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
}()
Then you call it like this:
Manager.upload(body.data(using: .utf8)!, to: url, method: .post, headers: headers)
Credits to Cnoon
My approach for self-signed https. The ServerTrustPolicyManager is an open class, and it's serverTrustPolicy function is open too. So it can be override.
In my case, the server list will grow in future. If I hard-code the https list, I will need to maintain the list when adding new https server. So, I decide to override the ServerTrustPolicyManager class in order to meet my needs.
// For Swift 3 and Alamofire 4.0
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
}
}
Then,
let trustPolicies = MyServerTrustPolicyManager(policies: [:])
let manager = Alamofire.SessionManager(configuration: sessionConfig, delegate: SessionDelegate(), serverTrustPolicyManager: trustPolicies)
So I know some time has passed, but I had exactly the same problem. And I found a solution with above answers. I had to add 2 things to trustPolicies:
let defaultManager: Alamofire.Manager = {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
// Here host with port (trustPolicy is my var where I pin my certificates)
"localhost:3443": trustPolicy
//Here without port
"localhost": .disableEvaluation
]
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
return Alamofire.Manager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}()
Also in Info.plist had to add:
<key>AppTransportSecurity</key>
<dict>
<key>AllowsArbitraryLoads</key>
<true/>
</dict>

Resources