How to set up local SSL certificate in the Rails Turbo iOS app?

I have a Rails app running locally on a custom .test domain on a Pow server and SSL certificate generated by Tunnelss gem.

Now I’m building a Hotwire Turbo iOS app, following the Quick Start Guide. The app already works fine when I set the URL to .com domain.

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let _ = (scene as? UIWindowScene) else { return }
    window!.rootViewController = navigationController
    visit(url: URL(string: "https://craftisian.test")!)
}

But when I set the URL to a local .test domain, Xcode shows An SSL error has occurred and a secure connection to the server cannot be made. error:

2021-12-22 09:06:54 +0000 - [ColdBootVisit] startVisit()
2021-12-22 10:06:55.731936+0100 App[20552:368484] [Process] 0x7fc94181ca20 - [pageProxyID=5, webPageID=6, PID=20587] WebPageProxy::didFailProvisionalLoadForFrame: frameID=3, domain=NSURLErrorDomain, code=-1200
didFailRequestForVisitable: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _WKRecoveryAttempterErrorKey=<WKReloadFrameErrorRecoveryAttempter: 0x600000687660>, networkTaskDescription=LocalDataTask <99C0B590-09BE-4BA2-8BE9-8276B5E45206>.<2>, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
    "<cert(0x7fc944905df0) s: *.dev i: *.dev Domain CA>",
    "<cert(0x7fc9449066e0) s: *.dev Domain CA i: *.dev Domain CA>"
), NSErrorFailingURLStringKey=https://craftisian.test/, NSUnderlyingError=0x6000008f1e30 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802}}, NSErrorClientCertificateStateKey=0, NSErrorFailingURLKey=https://craftisian.test/, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <99C0B590-09BE-4BA2-8BE9-8276B5E45206>.<2>, NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x6000037fc000>, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.}

I have the certificate added in Keychain and I also added it to the simulator.

1 Like

To use a local SSL certificate during testing, you can automatically trust a self-signed certificate with the following:

Find the ColdBootVisit.swift file in the Turbo library, and replace the following method in extension ColdBootVisit: WKNavigationDelegate.

    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        #if DEBUG
        guard let serverTrust = challenge.protectionSpace.serverTrust else { return completionHandler(.useCredential, nil) }
        let exceptions = SecTrustCopyExceptions(serverTrust)
        SecTrustSetExceptions(serverTrust, exceptions)
        completionHandler(.useCredential, URLCredential(trust: serverTrust))
        #else
        delegate?.visit(self, didReceiveAuthenticationChallenge: challenge, completionHandler: completionHandler)
        #endif
    }