Swift 2 – Xcode 7.0 Cannot Access HTTPS site with unstrusted SSL Certificate

Experts, I’m a Beginner in IOS 9 / XCODE 7 / Swift 2 Development Kit

I’m trying to create an ios app that simply route to Web Application in HTTPS protocol. Below is my code so far in ViewController.swift

  • How to remove the grey bottom bar in iPad simulator
  • Is there a way to reset the app between tests in Swift XCTest UI in Xcode 7?
  • Inconsistent SceneKit framerate
  • The working copy '<Project Name>' failed to commit files - Couldnt communicate with helper application
  • Can't access My Swift classes into Objective-C application
  • Xcode UI Tests can't find views that are added programatically
  • import UIKit
    
    class ViewController: UIViewController {
    
        @IBOutlet var myWebView: UIWebView!
    
        /**
         * Function to Display the Web Application initial URL
         */
        func loadAppURL(){
            let siteAddress = "https://domain:8443/path/to/page"
            let url = NSURL (string: siteAddress)
            let urlRequest = NSURLRequest(URL: url!)
            myWebView.loadRequest(urlRequest)
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            loadAppURL()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }
    

    While Building my App it shows the below Error Message

    2015-10-01 01:05:13.879 Web Page Tester[2947:31838]
    NSURLSession/NSURLConnection HTTP load failed
    (kCFStreamErrorDomainSSL, -9807)

    and if i try building my app instead of “https://domain:8443/path/to/page” with “http://www.apple.com” its works fine.

    I can access my web application in Safari and it asks for accepting the security risks. and i accept it and i can access my Application.

    Guide me to fix my issues, Thanks in advance.

    5 Solutions Collect From Internet About “Swift 2 – Xcode 7.0 Cannot Access HTTPS site with unstrusted SSL Certificate”

    Finally I fixed it

    Xcode will reject un-trusted self signed certificates from servers by default.

    we can override this Using NSURLConnection and can communicate with a self-signed server, since we have the ability to control the authentication through the additional delegate methods which are not available to a UIWebView. So using connection:didReceiveAuthenticationChallenge we can authenticate against the self signed server.

    References
    NSURLAuthenticationChallenge Docs , @Lilo Lu’s Question

    I Resolved My Issue in below steps
    Step 1 : Defined a NSURLConnection in viewDidLoad() method of my viewController.swift as follows

     override func viewDidLoad() {
        super.viewDidLoad()
    
        let siteAddress = "https://domain:8443/path/to/page"
        let url = NSURL (string: siteAddress)
        let urlRequest = NSURLRequest(URL: url!)
        let urlConnection:NSURLConnection = NSURLConnection(request: request, delegate: self)!
        myWebView.loadRequest(urlRequest)
     }
    

    Step 2 : used NSURLConnection delegate methods

        func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool{
            print("canAuthenticateAgainstProtectionSpace method Returning True")
            return true
        }
    
    
        func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge){
    
            print("did autherntcationchallenge = \(challenge.protectionSpace.authenticationMethod)")
    
            if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust  {
                print("send credential Server Trust")
                let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
                challenge.sender!.useCredential(credential, forAuthenticationChallenge: challenge)
    
            }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic{
                print("send credential HTTP Basic")
                let defaultCredentials: NSURLCredential = NSURLCredential(user: "username", password: "password", persistence:NSURLCredentialPersistence.ForSession)
                challenge.sender!.useCredential(defaultCredentials, forAuthenticationChallenge: challenge)
    
            }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM{
                print("send credential NTLM")
    
            } else{
                challenge.sender!.performDefaultHandlingForAuthenticationChallenge!(challenge)
          }
    }
    

    and that worked !!

    You can add the following to your plist

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    

    enter image description here

    In Swift 3.

    Step 1. Add NSURLConnectionDelegate to your viewcontroller, to overwrite methods.

    class ViewController: UIViewController, NSURLConnectionDelegate {
    

    Step 2. Override viewDidLoad

    override func viewDidLoad() {
            super.viewDidLoad()
    
            let siteAddress = "https://mysiteaddress"
            let url = URL(string: siteAddress)
            let urlRequest = URLRequest(url: url!)
            let urlConnection:NSURLConnection = NSURLConnection(request: urlRequest, delegate: self)!
            webView.loadRequest(urlRequest)
        }
    

    Step 3 Overwrite canAuthenticateAgainstProtectionSpace and didReceive challenge

    func connection(_ connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: URLProtectionSpace) -> Bool {
        print("\ncanAuthenticateAgainstProtectionSpace method Returning True\n")
        return true
    }
    
    func connection(_ connection: NSURLConnection, didReceive challenge: URLAuthenticationChallenge) {
        print("did autherntcationchallenge = \(challenge.protectionSpace.authenticationMethod)")
    
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust  {
            print("\nsend credential Server Trust\n")
            let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
            challenge.sender!.use(credential, for: challenge)
    
        }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic{
            print("send credential HTTP Basic")
            let defaultCredentials: URLCredential = URLCredential(user: "user", password: "password", persistence:URLCredential.Persistence.forSession)
            challenge.sender!.use(defaultCredentials, for: challenge)
    
        }else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM{
            print("\nsend credential NTLM\n")
    
        } else{
            challenge.sender!.performDefaultHandling!(for: challenge)
        }
    
    }
    

    Thanks Navas Basheer for the original solution! Saved me a ton of time

    1- Create category “NSURLRequestCategory” -> after import this category to your bridge file created by xcode (don’t forget to let xCode create one if you dont haven’t) and put this code :

        @implementation NSURLRequest (NSURLRequestCategory)
    
    + (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host
    {
        return YES;
    }
    @end
    

    Create your load request UIWebView normally :

    webView.delegate = self
    let myURL = URL(string: Constants.URL_DOMAINE)
    let request = URLRequest(url: myURL!)
    webView.loadRequest(request)
    

    Enjoyyy 😀

    edit Info.plist, Add:

    1. App Transport Security Settings
    2. Allow Arbitrary Loads , value is YES

    it’s work for me, XCode 7.3