Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alamofire with a self-signed certificate / ServerTrustPolicy

Tags:

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":"[email protected]","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 
like image 283
teawithfruit Avatar asked Sep 13 '15 18:09

teawithfruit


2 Answers

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)     ) }() 
like image 110
cnoon Avatar answered Oct 02 '22 14:10

cnoon


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

like image 31
William Kinaan Avatar answered Oct 02 '22 13:10

William Kinaan