How to Connect to Self Signed Servers Using Alamofire 1.3

How to connect to self signed servers using Alamofire 1.3

There is a way to change the Server Trust Policy of the Alamofire manager shared instance, but it's not recommended. Instead you should create your own customised instance of the manager. Here is the recommended solution, code is Swift 2.0 with Alamofire from swift-2.0 branch, compiled in Xcode7 beta 5.

Creating customised instance of the manager

Because you will not use the request method on the Alamofire, but use the one on your custom manager instead, you need to think of where to store the manager. What I do is to store it as static in my networking wrapper (the class that utilizes Alamofire and deals with my application networking needs). I set it up like this:

private static var Manager : Alamofire.Manager = {
// Create the server trust policies
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"maskeddomain.com": .DisableEvaluation
]
// Create custom manager
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
let man = Alamofire.Manager(
configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
return man
}()

Next step is to switch all your calls that use Alamofire.request() with Manager.request(), so you should have something like this:

Manager.request(.GET, "http://stackoverflow.com").responseJSON(
completionHandler: { (_, respose, result) -> Void in
if result.isSuccess {
// enjoy your success
} else if result.isFailure {
// deal with your failure
}
})

If you want to change the shared instance of the manager anyway, go here for more info.

How can I make Alamofire perform HTTPS request, using a certificate self-signed by an Unknown CA?

First you need to include your self signed ssl certificate in your apps target.

Note: The certificate must be in a format that iOS can read. You may need to convert your truststore-root.cer file to a different format. In some cases this is a trial and error procedure.

Then you can adjust your code to use the convenient certificates(in:) function of ServerTrustPolicy like this:

let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: false
)

let serverTrustPolicies = [
"192.168.50.31": serverTrustPolicy
]

return Alamofire.SessionManager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)

This function will scan your main bundle and return all the included files with one of the following suffixes ".cer", ".CER", ".crt", ".CRT", ".der", ".DER".

UPDATE: You can follow this answer to download your ssl certificate from the terminal. Then double click it to import it to your Keychain. Finaly you can export your certificate from the Keychain as a .cer file. This has the correct format that iOS can read. Verify that this is the case by manually invoking the certificates(in:) function of ServerTrustPolicy. It should now return your certificate.

How to implement self signed certificates in Alamofire?

This feature is not yet supported by Alamofire. It will most likely be added eventually by the community, but that work has yet to be submitted to the project. If you feel like contributing this feature, by all means fork the repo and submit a pull request.

If you want to learn how to implement this feature yourself, I'd suggest you read up on SSL pinning and TLS verification on iOS. You could also browse the source code in AFNetworking to get a feel of how it could possibly be implemented.

If you do not have time to build this feature yourself, then I suggest you use AFNetworking for the time being in your Swift app. AFNetworking is perfectly compatible with Swift and does support TLS verification.

How Can I Access Local Https with invalid certificate With Alamofire?

I finally sorted out my problems. There were two problems.

1. I needed to declare sessionManager outside the function.

let manager = SessionManager(configuration: URLSessionConfiguration.default, serverTrustPolicyManager: ServerTrustPolicyManager(policies:["localhost":.disableEvaluation]))

2. I read somewhere that you need to include port number for the host, but that actually caused the problem for me.

It seems like you just need to write "localhost" Instead of "localhost:443".

Regardless, here is the entire code that will disable evaluation for all addresses.

You don't need to change anything to Info.plist. The default Info.plist that Xcode gives you seem to work.

IOS 10.3.2, Xcode 8.3.2, Alamofire Master branch from Github (2017-05-23)

import UIKit
import Alamofire

class ViewController: UIViewController {

open class MyServerTrustPolicyManager: ServerTrustPolicyManager {
open override func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? {
return ServerTrustPolicy.disableEvaluation
}
}

let sessionManager = SessionManager(delegate:SessionDelegate(), serverTrustPolicyManager:MyServerTrustPolicyManager(policies: [:]))

func connect() {
let user = "user"
let password = "password"
let parameters:Parameters = ["parameter1":"value1", "parameter2":"value2"]
sessionManager.request("https://localhost:443/index.php", parameters:parameters).authenticate(user:user, password:password).responseString {
response in
debugPrint(response.result.value)
} else {
debugPrint(response)
}
}
}

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
connect()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

}

Alamofire 5 with self-signed certificate

It's very similar in Alamofire 5 but ServerTrustPolicy has been refactored into a protocol with conforming types for better extensibility. Similar to the answer you linked, you'll need to create a ServerTrustManager for your domain:

let manager = ServerTrustManager(evaluators: ["your.domain.here": DisabledTrustEvaluator()])
let session = Session(serverTrustManager: manager)

Of course, you'll still need to add ATS exceptions for your domains as well.

Additionally, you should never ship code that uses the DisabledTrustEvaluator, as it would allow all invalid TLS connections.

Alamofire tests include self-signed cert?

The majority of the certificates that exist in the Alamofire test suite are actually self-signed certs. It works exactly as you would expect.

All the data task tests that are written can easily be converted to download task tests by switching the name and providing a destination parameter. This will download the data into a temporary file instead of reading it into memory. Otherwise they're more or less the same operation.

Additionally, all server trust challenges are handled by the same ServerTrustPolicy. Data, Download and Upload requests are all handled in the same way.

Best of luck.

Secure connection can't be made

You need to change NSExceptionAllowsInsecureHTTPLoads to YES.

NSExceptionAllowsInsecureHTTPLoads

Set the value for this key to YES to allow insecure HTTP loads for the given domain, or to be able
to loosen the server trust evaluation requirements for HTTPS
connections to the domain
, as described in Performing Manual Server
Trust Authentication.

How to Connect localhost (with invalid certificate) using Alamofire?

You can easily override the default challenge behavior in Alamofire using the SessionDelegate override closures. Here is an example of how you can allow Alamofire to accept invalid certificates:

IMPORTANT: Please do not use this in any production code. Security is VERY important and this implementation completely disregards the security mechanisms in Alamofire. Use at your own risk!

let manager = Alamofire.Manager.sharedInstance

manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?

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)
}

We (the Alamofire TC) are going to implement TLS pinning and several other features related to security in the Alamofire 1.3.0 release.


UPDATE

The Alamofire 1.3.0 release is out and adds MUCH better support for customizing server trust authentication challenges. For further info, please check out the Security section of the README.



Related Topics



Leave a reply



Submit