Bug reproduction code:
Let the following run for 15 minutes or so* and you'll see that sending still succeeds although the token should have expired.
var hostName = ...
var deviceId = ...
var sasToken = new SharedAccessSignatureBuilder
{
Key = sharedAccessKey,
Target = $"{hostName}/devices/{deviceId}",
TimeToLive = TimeSpan.FromMinutes(5)
}
.ToSignature();
var authenticationMethod = new DeviceAuthenticationWithToken(deviceId, sasToken);
var connectionString = IotHubConnectionStringBuilder
.Create(hostName, authenticationMethod)
.ToString();
var deviceClient = DeviceClient
.CreateFromConnectionString(connectionString, TransportType.Mqtt);
while (true)
{
Console.WriteLine($"{DateTime.UtcNow}: Sending");
var messageContent = Encoding.UTF8.GetBytes("{}");
var message = new Message(messageContent);
await deviceClient.SendEventAsync(message);
await Task.Delay(TimeSpan.FromSeconds(10));
}
Correct me if I'm wrong, but does that mean that an open connection never expires? Whose fault is this? I would say that the IoT Hub should close the connection when the token expires, right?
* Internally a token seems to be valid for five more minutes, because that's what they define as MaxClockSkew
. So to save you some time you can set SharedAccessSignatureBuilder.TimeToLive
to -4.9 minutes and the token should expire within 0.1 minutes.
This is a bug that has already been reported - at the moment if you use MQTT, the token is checked when the device connects, but the device is not disconnected by IoT Hub when the token expires. I don't have a public link to the issue. I just tried with AMQP and got an authorization error when the SAS expired, same happens with HTTP. So the problem only exists with MQTT protocol currently.