Socket.io-client-swift: Socket not connecting to an https:// url

Created on 30 Dec 2016  路  8Comments  路  Source: socketio/socket.io-client-swift

Socket is giving this warning : ERROR SocketEnginePolling: An SSL error has occurred and a secure connection to the server cannot be made.
While this error is also producing in the log " NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9806) "

I have included .secure(true) in the config. but still socket is giving above mentioned errors and is not connecting.

Most helpful comment

Okay got it working...

let  file_der = Bundle.main.path(forResource: "certificate", ofType: "der")
var certs = [SSLCert]()
if let certificateData = try? Data(contentsOf: URL(fileURLWithPath: file_der!)) as Data {
     let certificate = SSLCert(data: certificateData)
      certs.append(certificate)
}
socket = SocketIOClient(
        socketURL: URL(string: "https://serverurl:8081")!,
        config: [.connectParams(["token": token]),
                 .log(true),
                 .selfSigned(true),
                 .forceWebsockets(true), 
                 .security(SSLSecurity(certs: certs, usePublicKeys: true)),
                .forceNew(true)
])

All 8 comments

If you are using a self signed certificate you have to force using socket instead of upgrade negotiation. The way the library is currently structured, the option to accept self signed certs is passed straight to the socket engine, but your connection will fail at the URLSession level.

@bilawal-liaqat hello, did you resolve your problem?

I am trying to PIN a self-signed cert and configuring the socket with URLSessionDelegate

socket = SocketIOClient(
socketURL: URL(string: "https://serverurl:8081")!,
config: [.connectParams(["token": token]),
.log(true),
.forceNew(true),
.selfSigned(true),
.sessionDelegate(appDelegate)
])`

but AppDelegate.urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler) method never gets called! What am I missing?

Looks like selfSigned(true) making the app to just ignore the certificate.

I also tried

socket = SocketIOClient(
socketURL: URL(string: "https://serverurl:8081")!,
config: [.connectParams(["token": token]),
.log(true),
.sessionDelegate(appDelegate),
.forceWebsockets(true),
.security(SSLSecurity(usePublicKeys: false)),
.forceNew(true)
])

with this I am getting SocketIOClient: Handling event: error with data: ["Invalid SSL certificate"]

Okay got it working...

let  file_der = Bundle.main.path(forResource: "certificate", ofType: "der")
var certs = [SSLCert]()
if let certificateData = try? Data(contentsOf: URL(fileURLWithPath: file_der!)) as Data {
     let certificate = SSLCert(data: certificateData)
      certs.append(certificate)
}
socket = SocketIOClient(
        socketURL: URL(string: "https://serverurl:8081")!,
        config: [.connectParams(["token": token]),
                 .log(true),
                 .selfSigned(true),
                 .forceWebsockets(true), 
                 .security(SSLSecurity(certs: certs, usePublicKeys: true)),
                .forceNew(true)
])

@rajeevwhiz is there a way to make this work __without__ forcing web sockets only? Can the long polling transport be configured to be pinned to your ssl cert?

@rajeevwhiz How do I import SSLCert?
If your method works, it's exactly what I'm looking for.

found it. Had to import Starscream

Tried your code and it is complaining that I need to pass manager when constructing SocketIOClient.

I couldn't get your code to compile.
Following the docs I've reached the following snippet:

        let  ca_cert = Bundle.main.path(forResource: "ca", ofType: "cert")
        let  intermediate_cert = Bundle.main.path(forResource: "intermediate", ofType: "cert")
        var certs = [SSLCert]()
        if let certificateData = try? Data(contentsOf: URL(fileURLWithPath: ca_cert!)) as Data {
            let certificate = SSLCert(data: certificateData)
            certs.append(certificate)
        }

        if let certificateData = try? Data(contentsOf: URL(fileURLWithPath: intermediate_cert!)) as Data {
            let certificate = SSLCert(data: certificateData)
            certs.append(certificate)
        }

        let security: SocketIO.SSLSecurity = SocketIO.SSLSecurity(certs: certs, usePublicKeys: false)
        security.security.validatedDN = false

        let manager = SocketManager(
            socketURL: URL(string: "https://myip:5000")!,
            config: [
                //.connectParams(["token": token])
                .log(true),
                .selfSigned(true),
                .forceWebsockets(true),
                .forceNew(true),
                .security(security)]
        )

        let socket = manager.defaultSocket

        socket.on(clientEvent: .connect) {data, ack in
            os_log("Socket connected!", type: .debug)
        }

        socket.on("test") {data, ack in
            guard let test = data[0] as? String else { return }

            os_log("on test: %s", type: .debug, test)
        }

        socket.connect()

I'm not seeing the invalid Certificate error, but I'm also not getting a success connect.
Could you point me in the right direction?

EDIT:

  1. So I wasn't seeing a connect because the SocketManager was being released.
  2. Digging some more on the docs I discovered I had to disable domain validation since my server is running on a local network with no guarantee of static ip/domain.
  3. After those changes, I think I found a bug in Starscream. More details on daltoniam/Starscream#378
Was this page helpful?
0 / 5 - 0 ratings