Hello,
We are using Microsoft.Azure.Devices.Client 1.7.2 and trying to send a message to the iot hub. We are creating our device client using the following code:
var deviceClient = DeviceClient.Create(_iotHubConfiguration.HostName, new DeviceAuthenticationWithX509Certificate(_iotHubConfiguration.DeviceName, _iotHubConfiguration.Certificate),
TransportType.Mqtt_WebSocket_Only);
The cert is the pfx cert. This works fine when switching to Mqtt protocol. I have tried every protocol available. Mqtt over websockets and Amqp over websockets both return unauthorized. Mqtt and Amqp work. Is this a known issue? Any guidance on how to get this to work?
Thanks.
It appears X509 authentication is not supported over the *_WS or https protocols according to the docs
MS please confirm if this is still the case
Hi @adamkjonesmesh and @kzeronik
X.509 based authentication is not currently supported over port 443 as mentioned in the readme.md located at https://github.com/Azure/azure-iot-sdk-csharp/
Examples
DeviceAuthenticationWithX509Certificate authMethod = new
DeviceAuthenticationWithX509Certificate("mydevice", x509Certificate);
This will not work
1.) DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Http1);
2.) DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Mqtt_WebSocket_Only);
3.) DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Amqp_WebSocket_Only);
This should work
1.) DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Mqtt_Tcp_Only);
2.) DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Amqp_Tcp_Only);
The reason it throws an authorization error for web socket connection is because during TLS handshake, the client application has to send the client side certificate as the device is configured to use X.509 authentication. Client application using the SDK doesn't send it for web socket connection.
Since Hub doesn't get this client side certificate, it rejects the connection. That is why you see CONNECT failed: RefusedNotAuthorized error.
Ok, thank you. Does anyone know if this is something in the backlog to implement?
Thanks @anhashia for taking point and answering this!
Does anyone know if this is something in the backlog to implement?
Yes, one reason we didn't implement this yet was this .NET Core feature, now available in 2.1: https://github.com/dotnet/corefx/wiki/ApiCompat#clientwebsocketoptions.
@tameraw @yzhong94 FYI
When I test this issue with self-signed certificate, it works fine. So i don't think the reason is about the service-end.
@v-liujxu
I received the same error (CONNECT failed: RefusedNotAuthorized) using a self-signed certificate and Mqtt_WebSocket_Only transport type. Can you provide some additional details for your self-signed cert test?
@mikermesh
I created the a self-signed device named 'testDevice' with SimpleAzureIoTCerts, and then tested with the following code, it works, i can receive the messages in Device Explorer:
private static int MESSAGE_COUNT = 3;
private const int TEMPERATURE_THRESHOLD = 30;
private static String deviceId = "testDevice";
private static float temperature;
private static float humidity;
private static Random rnd = new Random();
static void Main(string[] args)
{
try
{
var cert = new X509Certificate2("primary.pfx", "");
var auth = new DeviceAuthenticationWithX509Certificate(deviceId, cert);
var deviceClient = DeviceClient.Create("{iot hub host name}", auth, TransportType.Mqtt_WebSocket_Only);
if (deviceClient == null)
{
Console.WriteLine("Failed to create DeviceClient!");
}
else
{
Console.WriteLine("Successfully created DeviceClient!");
SendEvent(deviceClient).Wait();
}
Console.WriteLine("Exiting...\n");
}
catch (Exception ex)
{
Console.WriteLine("Error in sample: {0}", ex.Message);
}
Console.Read();
}
private static async Task SendEvent(DeviceClient deviceClient)
{
string dataBuffer;
Console.WriteLine("Device sending {0} messages to IoTHub...\n", MESSAGE_COUNT);
for (int count = 0; count < MESSAGE_COUNT; count++)
{
temperature = rnd.Next(20, 35);
humidity = rnd.Next(60, 80);
dataBuffer = string.Format("{{\"deviceId\":\"{0}\",\"messageId\":{1},\"temperature\":{2},\"humidity\":{3}}}", deviceId, count, temperature, humidity);
Message eventMessage = new Message(Encoding.UTF8.GetBytes(dataBuffer));
eventMessage.Properties.Add("temperatureAlert", (temperature > TEMPERATURE_THRESHOLD) ? "true" : "false");
Console.WriteLine("\t{0}> Sending message: {1}, Data: [{2}]", DateTime.Now.ToLocalTime(), count, dataBuffer);
await deviceClient.SendEventAsync(eventMessage);
System.Threading.Thread.Sleep(1000);
}
}
Thanks @v-liujxu. Is your project targeting .NET Framework? According to the README, websocket support for MQTT/AMQP is limited to .NET Framework 4.x. Our project is targeting Core.
Note * WebSocket support for MQTT/AMQP is limited to .NET Framework 4.x.
This works now for NetStandard2.0 runtimes with support for WebSocket and Client Certificates (e.g. netcoreapp2.1)
Fixed by #577.
@kzeronik, @adamkjonesmesh, @v-liujxu, @mikermesh, thank you for your contribution to our open-sourced project! Please help us improve by filling out this 2-minute customer satisfaction survey
Most helpful comment
Hi @adamkjonesmesh and @kzeronik
X.509 based authentication is not currently supported over port 443 as mentioned in the readme.md located at https://github.com/Azure/azure-iot-sdk-csharp/
Examples
DeviceAuthenticationWithX509Certificate authMethod = new DeviceAuthenticationWithX509Certificate("mydevice", x509Certificate);This will not work
1.)
DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Http1);2.)
DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Mqtt_WebSocket_Only);3.)
DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Amqp_WebSocket_Only);This should work
1.)
DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Mqtt_Tcp_Only);2.)
DeviceClient deviceClient = DeviceClient.Create("MyHub.azure-devices.net", authMethod, TransportType.Amqp_Tcp_Only);The reason it throws an authorization error for web socket connection is because during TLS handshake, the client application has to send the client side certificate as the device is configured to use X.509 authentication. Client application using the SDK doesn't send it for web socket connection.
Since Hub doesn't get this client side certificate, it rejects the connection. That is why you see
CONNECT failed: RefusedNotAuthorizederror.