How to Connect Localhost (With Invalid Certificate) Using Alamofire

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.

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

}

The certificate is invalid when connecting iOS app to an api running on localhost with Alamofire

I did it by combining ReinerMelian's answer with one of the answers in the other question

ViewController:

class TableViewController: UIViewController {

let postClient = PostServiceClient.sharedInstance

override func viewDidLoad() {
super.viewDidLoad()

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

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

return (disposition, credential)
}

postClient.getPosts()
}
}

Service Client:

class PostServiceClient {

static let sharedInstance: PostServiceClient = PostServiceClient()

var sessionManager : SessionManager!

init() {
self.sessionManager = SessionManager(configuration: URLSessionConfiguration.default)
}
static let url = URL.init(string: "https://127.0.0.1:8000/post/")

// Methods to get posts from the wall
func getPosts(){
print("Getting posts with completion handler")
var request = URLRequest(url: PostServiceClient.url!)
request.httpMethod = "GET"
self.sessionManager.request(request).responseJSON { (response) in
guard response.result.isSuccess else {
print("Error while getting posts: \(String(describing: response.result.error))")
return
}
guard let responseJSON = response.result.value as? [String: Any],
let results = responseJSON["results"] as? [[String: Any]] else {
print("Invalid response recieved from service")
return
}
print(responseJSON)
}

}
}

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.

Disable HTTPS GET certificate check

add this entry to info.plist

<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>server.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>

and use the HTTP insteasd of HTTPS in URL



Related Topics



Leave a reply



Submit