3

I need to reach an API which has a invalid certificate and a basic Auth. As I searched, I needed to write custom SessionManager and add an value to plist file. After days of search and lots of posts, I can't still reach the API.

struct CustomManagerClass{

static let instance = CustomManagerClass()
var sessionManager : SessionManager = {

    let serverTrustPolicies: [String: ServerTrustPolicy] = [
        "baseurl.com:8443": .disableEvaluation
    ]

    // Create custom manager
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
    let manager = Alamofire.SessionManager(
        configuration: configuration,
        serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )

    return manager
}()

Plist File:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>baseurl.com</key>
    <dict>
        <key>NSTemporaryExceptionMinimumTLSVersion</key>
        <string>TLSv1.2</string>
        <key>NSIncludesSubdomains</key>
        <true/>
        <key>NSExceptionRequiresForwardSecrecy</key>
        <false/>
        <key>NSExceptionAllowsInsecureHTTPLoads</key>
        <true/>
    </dict>
</dict>

How I call it:

CustomManagerClass.instance.sessionManager.request(route).responseJSON(completionHandler: { (result) in
        completion(result)
    }) //Route in here is a ServiceConfiguration class which defines http method, parameters and basic auth.

It still returns;

Task <4CE5991B-2650-471C-AB77-69D54B8E36F3>.<1> finished with error - code: -1202 The certificate for this server is invalid. You might be connecting to a server that is pretending to be “baseurl.com” which could put your confidential information at risk.

Posts I got help: Certificate Invalid Issue with Alamofire 4.0

How to use Alamofires ServerTrustPolicy.disableEvaluation in swift 3

EDIT: I add below code to trust certificate. Now It returns HTTP 500

 CustomManagerClass.instance.sessionManager.delegate.sessionDidReceiveChallenge = { session, challenge in
        var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
        var credential: URLCredential?

        print("received challenge")

        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            disposition = URLSession.AuthChallengeDisposition.useCredential
            credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
        } else {
            if challenge.previousFailureCount > 0 {
                disposition = .cancelAuthenticationChallenge
            } else {
                credential = CustomManagerClass.instance.sessionManager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)

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

        return (disposition, credential)
    }
Emre Önder
  • 2,408
  • 2
  • 23
  • 73

1 Answers1

2

I'd suggest to add this handler for the sessionDidReceiveChallenge event on the SessionManager delegate.

let challengeHandler: ((URLSession, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))? = { result, challenge in
    return (.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}

And then assign the closure when you're initializing the manager object in this way.

manager.delegate.sessionDidReceiveChallenge = challengeHandler

Also, the serverTrustPolicies can be empty since the handler is going to ignore all the trust challenges it will receive.