Disconnected from MQTT, error: Optional(Error Domain=MGCDAsyncSocketErrorDomain Code=8 "Error in SSLSetCertificate" UserInfo={NSLocalizedDescription=Error in SSLSetCertificate})

Shahanshah Alam 0 Reputation points
2024-10-10T06:30:29.5366667+00:00

I am trying to connect with MQTT with DigiCert G2 .crt certificate from https://free.blessedness.top/en-us/azure/security/fundamentals/azure-ca-details?tabs=root-and-subordinate-cas-list#root-certificate-authorities, I am getting this error.

Disconnected from MQTT, error: Optional(Error Domain=MGCDAsyncSocketErrorDomain Code=8 "Error in SSLSetCertificate" UserInfo={NSLocalizedDescription=Error in SSLSetCertificate})

pod 'CocoaMQTT', :modular_headers => true pod 'MqttCocoaAsyncSocket', :modular_headers => true

Anything which I am doing wrong here?

import Foundation
import CocoaMQTT

class MQTTManager: CocoaMQTTDelegate {
    func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: (any Error)?) {
        print("Disconnected from MQTT, error: \(String(describing: err))\n")
    }
    var mqtt: CocoaMQTT!
    func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16) {
        print("Published message with ID: \(id)")  }
    func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String]) {
        print("Subscribed to topics: \(success)")  }
    func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopics topics: [String]) {
        print("Unsubscribed from topics: \(topics)")
    }
    func mqttDidPing(_ mqtt: CocoaMQTT) {
        print("Pinged!")}
    func mqttDidReceivePong(_ mqtt: CocoaMQTT) {
        print("Ponged!") }
    func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: (Error?)?) {
        print("Disconnected from MQTT, error: \(String(describing: err))")
    }
    func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) {
        if ack == .accept {
            print("Connected to the MQTT broker!")
            // Subscribe to a topic only after a successful connection
            subscribeToTopic(topic: "your-topic")
        } else {
            print("Failed to connect to MQTT")
        }
    }
    func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) {
        print("Published message: \(message.string ?? "") with ID: \(id)")
    }
    func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) {
        if let messageString = message.string {
            print("Received message on topic \(message.topic): \(messageString)")
        }
    }
    func connectMQTT(sasToken: String, assignedHub: String, registrationId: String,uuid: String, certificate: String, otp: String,deviceKey: String, modelId: String) {
        mqtt = CocoaMQTT(clientID: registrationId, host: assignedHub, port: 8883)
        print("Attempting to connect to MQTT broker... with client ID:\(String(describing: mqtt)) & \(mqtt.clientID)")
        mqtt.delegate = self
        mqtt.username = "\(assignedHub)/\(registrationId)/?api-version=2021-04-12";
        mqtt.password = sasToken;
        let certPath = Bundle.main.path(forResource: "DigiCertGlobalRootG2", ofType: "crt")!
              let certData = try? Data(contentsOf: URL(fileURLWithPath: certPath))
              let sslSettings: [String: NSObject] = [
                  kCFStreamSSLPeerName as String: assignedHub as NSObject,
                  kCFStreamSSLCertificates as String: [certificate] as NSObject
              ]
        mqtt.allowUntrustCACertificate = true
        mqtt.sslSettings=sslSettings
        mqtt.connect()
    }
}

Azure IoT Hub
Azure IoT Hub
An Azure service that enables bidirectional communication between internet of things (IoT) devices and applications.
Azure IoT SDK
Azure IoT SDK
An Azure software development kit that facilitates building applications that connect to Azure IoT services.
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Amira Bedhiafi 39,106 Reputation points Volunteer Moderator
    2025-09-10T20:11:28.48+00:00

    Hello Shahanshand !

    Thank you for posting on Microsoft Learn Q&A.

    On iOS, kCFStreamSSLCertificates is ONLY for a client identity (cert + private key) when you’re doing mutual-TLS, not for a CA root. It must be an array whose first element is a SecIdentity (private key + cert), followed by any intermediate certs. Passing a .crt (a root CA) or a String path there triggers SSLSetCertificate errors like the one you’re seeing.

    https://developer.apple.com/documentation/cfnetwork/kcfstreamsslcertificates

    For Azure IoT Hub with SAS tokens you don’t need to ship DigiCert G2 at all since iOS already trusts it. Just use TLS on port 8883 and don't set kCFStreamSSLCertificates so you need to keep the peer name equal to the exact host and let system trust validation run.

    https://free.blessedness.top/en-us/azure/iot/iot-mqtt-connect-to-iot-hub

    So your SAS token auth must be like below :

    func connectMQTT(sasToken: String, hubHost: String, deviceId: String) {
        let mqtt = CocoaMQTT(clientID: deviceId, host: hubHost, port: 8883)
        mqtt.username = "\(hubHost)/\(deviceId)/?api-version=2021-04-12"
        mqtt.password = sasToken
        mqtt.enableSSL = true
        mqtt.allowUntrustCACertificate = false 
        mqtt.sslSettings = [ kCFStreamSSLPeerName as String: hubHost as NSObject ]
        mqtt.connect()
    }
    
    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.