mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-27 08:42:37 +08:00
Fix support for enhanced authentication (#2132)
* Implement enhanced authentication for client and server. * Update samples * Add abstraction layer * Merge master * Use dedicated class for public API. * Update release notes * Rename methods to fit naming scheme * Fix unit tests and samples
This commit is contained in:
-63
@@ -1,63 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet;
|
||||
|
||||
public class MqttExtendedAuthenticationExchangeContext
|
||||
{
|
||||
public MqttExtendedAuthenticationExchangeContext(MqttAuthPacket authPacket, MqttClient client)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(authPacket);
|
||||
|
||||
ReasonCode = authPacket.ReasonCode;
|
||||
ReasonString = authPacket.ReasonString;
|
||||
AuthenticationMethod = authPacket.AuthenticationMethod;
|
||||
AuthenticationData = authPacket.AuthenticationData;
|
||||
UserProperties = authPacket.UserProperties;
|
||||
|
||||
Client = client ?? throw new ArgumentNullException(nameof(client));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authentication data.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public byte[] AuthenticationData { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authentication method.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public string AuthenticationMethod { get; }
|
||||
|
||||
public MqttClient Client { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reason code.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public MqttAuthenticateReasonCode ReasonCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reason string.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public string ReasonString { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user properties.
|
||||
/// In MQTT 5, user properties are basic UTF-8 string key-value pairs that you can append to almost every type of MQTT
|
||||
/// packet.
|
||||
/// As long as you don’t exceed the maximum message size, you can use an unlimited number of user properties to add
|
||||
/// metadata to MQTT messages and pass information between publisher, broker, and subscriber.
|
||||
/// The feature is very similar to the HTTP header concept.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public List<MqttUserProperty> UserProperties { get; }
|
||||
}
|
||||
@@ -2,24 +2,23 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MQTTnet.Formatter
|
||||
{
|
||||
public struct ReadFixedHeaderResult
|
||||
{
|
||||
public static ReadFixedHeaderResult Canceled { get; } = new ReadFixedHeaderResult
|
||||
{
|
||||
IsCanceled = true
|
||||
};
|
||||
|
||||
public static ReadFixedHeaderResult ConnectionClosed { get; } = new ReadFixedHeaderResult
|
||||
{
|
||||
IsConnectionClosed = true
|
||||
};
|
||||
|
||||
public bool IsCanceled { get; set; }
|
||||
|
||||
public bool IsConnectionClosed { get; set; }
|
||||
namespace MQTTnet.Formatter;
|
||||
|
||||
public MqttFixedHeader FixedHeader { get; set; }
|
||||
}
|
||||
}
|
||||
public struct ReadFixedHeaderResult
|
||||
{
|
||||
public static ReadFixedHeaderResult Canceled { get; } = new()
|
||||
{
|
||||
IsCanceled = true
|
||||
};
|
||||
|
||||
public static ReadFixedHeaderResult ConnectionClosed { get; } = new()
|
||||
{
|
||||
IsConnectionClosed = true
|
||||
};
|
||||
|
||||
public bool IsCanceled { get; set; }
|
||||
|
||||
public bool IsConnectionClosed { get; init; }
|
||||
|
||||
public MqttFixedHeader FixedHeader { get; init; }
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace MQTTnet.Formatter.V5
|
||||
{
|
||||
public sealed class MqttV5PacketDecoder
|
||||
{
|
||||
readonly MqttBufferReader _bufferReader = new MqttBufferReader();
|
||||
readonly MqttBufferReader _bufferReader = new();
|
||||
|
||||
public MqttPacket Decode(ReceivedMqttPacket receivedMqttPacket)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ public interface IMqttClient : IDisposable
|
||||
|
||||
Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken = default);
|
||||
|
||||
Task SendExtendedAuthenticationExchangeDataAsync(MqttExtendedAuthenticationExchangeData data, CancellationToken cancellationToken = default);
|
||||
Task SendEnhancedAuthenticationExchangeDataAsync(MqttEnhancedAuthenticationExchangeData data, CancellationToken cancellationToken = default);
|
||||
|
||||
Task<MqttClientSubscribeResult> SubscribeAsync(MqttClientSubscribeOptions options, CancellationToken cancellationToken = default);
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ public sealed class MqttClient : Disposable, IMqttClient
|
||||
}
|
||||
}
|
||||
|
||||
public Task SendExtendedAuthenticationExchangeDataAsync(MqttExtendedAuthenticationExchangeData data, CancellationToken cancellationToken = default)
|
||||
public Task SendEnhancedAuthenticationExchangeDataAsync(MqttEnhancedAuthenticationExchangeData data, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
|
||||
@@ -437,27 +437,30 @@ public sealed class MqttClient : Disposable, IMqttClient
|
||||
var connectPacket = MqttConnectPacketFactory.Create(options);
|
||||
await Send(connectPacket, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var receivedPacket = await Receive(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
switch (receivedPacket)
|
||||
while (true)
|
||||
{
|
||||
case MqttConnAckPacket connAckPacket:
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var receivedPacket = await Receive(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (receivedPacket is MqttAuthPacket authPacket)
|
||||
{
|
||||
await HandleEnhancedAuthentication(authPacket, cancellationToken);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (receivedPacket is MqttConnAckPacket connAckPacket)
|
||||
{
|
||||
result = MqttClientResultFactory.ConnectResult.Create(connAckPacket, channelAdapter.PacketFormatterAdapter.ProtocolVersion);
|
||||
break;
|
||||
}
|
||||
case MqttAuthPacket _:
|
||||
|
||||
if (receivedPacket != null)
|
||||
{
|
||||
throw new NotSupportedException("Extended authentication handler is not yet supported");
|
||||
}
|
||||
case null:
|
||||
{
|
||||
throw new MqttCommunicationException("Connection closed.");
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new InvalidOperationException($"Received an unexpected MQTT packet ({receivedPacket}).");
|
||||
throw new MqttProtocolViolationException($"Received other packet than CONNACK or AUTH while connecting ({receivedPacket}).");
|
||||
}
|
||||
|
||||
throw new MqttCommunicationException("Connection closed.");
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
@@ -470,6 +473,12 @@ public sealed class MqttClient : Disposable, IMqttClient
|
||||
return result;
|
||||
}
|
||||
|
||||
async Task HandleEnhancedAuthentication(MqttAuthPacket authPacket, CancellationToken cancellationToken)
|
||||
{
|
||||
var eventArgs = new MqttEnhancedAuthenticationEventArgs(authPacket, _adapter, cancellationToken);
|
||||
await Options.EnhancedAuthenticationHandler.HandleEnhancedAuthenticationAsync(eventArgs);
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
try
|
||||
@@ -646,12 +655,26 @@ public sealed class MqttClient : Disposable, IMqttClient
|
||||
return _events.ConnectedEvent.InvokeAsync(eventArgs);
|
||||
}
|
||||
|
||||
Task ProcessReceivedAuthPacket(MqttAuthPacket authPacket)
|
||||
Task ProcessReceivedAuthPacket(MqttAuthPacket authPacket, CancellationToken cancellationToken)
|
||||
{
|
||||
var extendedAuthenticationExchangeHandler = Options.ExtendedAuthenticationExchangeHandler;
|
||||
return extendedAuthenticationExchangeHandler != null
|
||||
? extendedAuthenticationExchangeHandler.HandleRequestAsync(new MqttExtendedAuthenticationExchangeContext(authPacket, this))
|
||||
: CompletedTask.Instance;
|
||||
if (Options.EnhancedAuthenticationHandler == null)
|
||||
{
|
||||
// From RFC: If the re-authentication fails, the Client or Server SHOULD send DISCONNECT with an appropriate Reason Code
|
||||
// as described in section 4.13, and MUST close the Network Connection [MQTT-4.12.1-2].
|
||||
//
|
||||
// Since we have no handler there is no chance to fulfil the re-authentication request.
|
||||
_ = DisconnectAsync(new MqttClientDisconnectOptions
|
||||
{
|
||||
Reason = MqttClientDisconnectOptionsReason.ImplementationSpecificError,
|
||||
ReasonString = "Unable to handle AUTH packet"
|
||||
},
|
||||
cancellationToken);
|
||||
|
||||
return CompletedTask.Instance;
|
||||
}
|
||||
|
||||
var eventArgs = new MqttEnhancedAuthenticationEventArgs(authPacket, _adapter, cancellationToken);
|
||||
return Options.EnhancedAuthenticationHandler.HandleEnhancedAuthenticationAsync(eventArgs);
|
||||
}
|
||||
|
||||
Task ProcessReceivedDisconnectPacket(MqttDisconnectPacket disconnectPacket)
|
||||
@@ -959,7 +982,7 @@ public sealed class MqttClient : Disposable, IMqttClient
|
||||
await ProcessReceivedDisconnectPacket(disconnectPacket).ConfigureAwait(false);
|
||||
break;
|
||||
case MqttAuthPacket authPacket:
|
||||
await ProcessReceivedAuthPacket(authPacket).ConfigureAwait(false);
|
||||
await ProcessReceivedAuthPacket(authPacket, cancellationToken).ConfigureAwait(false);
|
||||
break;
|
||||
case MqttPingRespPacket _:
|
||||
_packetDispatcher.TryDispatch(packet);
|
||||
|
||||
@@ -99,11 +99,11 @@ public static class MqttClientExtensions
|
||||
return client.ConnectAsync(client.Options, cancellationToken);
|
||||
}
|
||||
|
||||
public static Task SendExtendedAuthenticationExchangeDataAsync(this IMqttClient client, MqttExtendedAuthenticationExchangeData data)
|
||||
public static Task SendEnhancedAuthenticationExchangeDataAsync(this IMqttClient client, MqttEnhancedAuthenticationExchangeData data)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(client);
|
||||
|
||||
return client.SendExtendedAuthenticationExchangeDataAsync(data, CancellationToken.None);
|
||||
return client.SendEnhancedAuthenticationExchangeDataAsync(data, CancellationToken.None);
|
||||
}
|
||||
|
||||
public static Task<MqttClientSubscribeResult> SubscribeAsync(this IMqttClient mqttClient, MqttTopicFilter topicFilter, CancellationToken cancellationToken = default)
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace MQTTnet;
|
||||
|
||||
public interface IMqttExtendedAuthenticationExchangeHandler
|
||||
public interface IMqttEnhancedAuthenticationHandler
|
||||
{
|
||||
Task HandleRequestAsync(MqttExtendedAuthenticationExchangeContext context);
|
||||
Task HandleEnhancedAuthenticationAsync(MqttEnhancedAuthenticationEventArgs eventArgs);
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace MQTTnet;
|
||||
public sealed class MqttClientOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Usually the MQTT packets can be send partially. This is done by using multiple TCP packets
|
||||
/// Usually the MQTT packets can be sent partially. This is done by using multiple TCP packets
|
||||
/// or WebSocket frames etc. Unfortunately not all brokers (like Amazon Web Services (AWS)) do support this feature and
|
||||
/// will close the connection when receiving such packets. If such a service is used this flag must
|
||||
/// be set to _false_.
|
||||
@@ -38,7 +38,7 @@ public sealed class MqttClientOptions
|
||||
/// Gets or sets a value indicating whether clean sessions are used or not.
|
||||
/// When a client connects to a broker it can connect using either a non persistent connection (clean session) or a
|
||||
/// persistent connection.
|
||||
/// With a non persistent connection the broker doesn't store any subscription information or undelivered messages for
|
||||
/// With a non-persistent connection the broker doesn't store any subscription information or undelivered messages for
|
||||
/// the client.
|
||||
/// This mode is ideal when the client only publishes messages.
|
||||
/// It can also connect as a durable client using a persistent connection.
|
||||
@@ -54,7 +54,12 @@ public sealed class MqttClientOptions
|
||||
|
||||
public IMqttClientCredentialsProvider Credentials { get; set; }
|
||||
|
||||
public IMqttExtendedAuthenticationExchangeHandler ExtendedAuthenticationExchangeHandler { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the handler for AUTH packets.
|
||||
/// This can happen when connecting or at any time while being already connected.
|
||||
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||
/// </summary>
|
||||
public IMqttEnhancedAuthenticationHandler EnhancedAuthenticationHandler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the keep alive period.
|
||||
@@ -80,7 +85,7 @@ public sealed class MqttClientOptions
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the receive maximum.
|
||||
/// This gives the maximum length of the receive messages.
|
||||
/// This gives the maximum length of the received messages.
|
||||
/// <remarks>MQTT 5.0.0+ feature.</remarks>
|
||||
/// </summary>
|
||||
public ushort ReceiveMaximum { get; set; }
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet;
|
||||
|
||||
@@ -98,13 +98,6 @@ public sealed class MqttClientOptionsBuilder
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithAuthentication(string method, byte[] data)
|
||||
{
|
||||
_options.AuthenticationMethod = method;
|
||||
_options.AuthenticationData = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean session is used in MQTT versions below 5.0.0. It is the same as setting "CleanStart".
|
||||
/// </summary>
|
||||
@@ -138,27 +131,19 @@ public sealed class MqttClientOptionsBuilder
|
||||
{
|
||||
case "tcp":
|
||||
case "mqtt":
|
||||
WithTcpServer(uri.Host, port)
|
||||
.WithAddressFamily(AddressFamily.Unspecified)
|
||||
.WithProtocolType(ProtocolType.Tcp)
|
||||
.WithTlsOptions(o => o.UseTls(false));
|
||||
WithTcpServer(uri.Host, port).WithAddressFamily(AddressFamily.Unspecified).WithProtocolType(ProtocolType.Tcp).WithTlsOptions(o => o.UseTls(false));
|
||||
break;
|
||||
|
||||
case "mqtts":
|
||||
WithTcpServer(uri.Host, port)
|
||||
.WithAddressFamily(AddressFamily.Unspecified)
|
||||
.WithProtocolType(ProtocolType.Tcp)
|
||||
.WithTlsOptions(o => o.UseTls(true));
|
||||
WithTcpServer(uri.Host, port).WithAddressFamily(AddressFamily.Unspecified).WithProtocolType(ProtocolType.Tcp).WithTlsOptions(o => o.UseTls());
|
||||
break;
|
||||
|
||||
case "ws":
|
||||
WithWebSocketServer(o => o.WithUri(uri.ToString()))
|
||||
.WithTlsOptions(o => o.UseTls(false));
|
||||
WithWebSocketServer(o => o.WithUri(uri.ToString())).WithTlsOptions(o => o.UseTls(false));
|
||||
break;
|
||||
|
||||
case "wss":
|
||||
WithWebSocketServer(o => o.WithUri(uri.ToString()))
|
||||
.WithTlsOptions(o => o.UseTls(true));
|
||||
WithWebSocketServer(o => o.WithUri(uri.ToString())).WithTlsOptions(o => o.UseTls());
|
||||
break;
|
||||
|
||||
// unix:///path/to/socket
|
||||
@@ -220,9 +205,16 @@ public sealed class MqttClientOptionsBuilder
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithExtendedAuthenticationExchangeHandler(IMqttExtendedAuthenticationExchangeHandler handler)
|
||||
public MqttClientOptionsBuilder WithEnhancedAuthentication(string method, byte[] data = null)
|
||||
{
|
||||
_options.ExtendedAuthenticationExchangeHandler = handler;
|
||||
_options.AuthenticationMethod = method;
|
||||
_options.AuthenticationData = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MqttClientOptionsBuilder WithEnhancedAuthenticationHandler(IMqttEnhancedAuthenticationHandler handler)
|
||||
{
|
||||
_options.EnhancedAuthenticationHandler = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,11 @@ public static class MqttClientOptionsValidator
|
||||
{
|
||||
Throw(nameof(options.WillUserProperties));
|
||||
}
|
||||
|
||||
if (options.EnhancedAuthenticationHandler != null)
|
||||
{
|
||||
Throw(nameof(options.EnhancedAuthenticationHandler));
|
||||
}
|
||||
}
|
||||
|
||||
static void Throw(string featureName)
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Exceptions;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet;
|
||||
|
||||
public class MqttEnhancedAuthenticationEventArgs : EventArgs
|
||||
{
|
||||
readonly IMqttChannelAdapter _channelAdapter;
|
||||
readonly MqttAuthPacket _initialAuthPacket;
|
||||
|
||||
public MqttEnhancedAuthenticationEventArgs(MqttAuthPacket initialAuthPacket, IMqttChannelAdapter channelAdapter, CancellationToken cancellationToken)
|
||||
{
|
||||
_initialAuthPacket = initialAuthPacket ?? throw new ArgumentNullException(nameof(initialAuthPacket));
|
||||
_channelAdapter = channelAdapter ?? throw new ArgumentNullException(nameof(channelAdapter));
|
||||
|
||||
CancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authentication data.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public byte[] AuthenticationData => _initialAuthPacket.AuthenticationData;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authentication method.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public string AuthenticationMethod => _initialAuthPacket.AuthenticationMethod;
|
||||
|
||||
public CancellationToken CancellationToken { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reason code.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public MqttAuthenticateReasonCode ReasonCode => _initialAuthPacket.ReasonCode;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reason string.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public string ReasonString => _initialAuthPacket.ReasonString;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user properties.
|
||||
/// In MQTT 5, user properties are basic UTF-8 string key-value pairs that you can append to almost every type of MQTT
|
||||
/// packet.
|
||||
/// As long as you don’t exceed the maximum message size, you can use an unlimited number of user properties to add
|
||||
/// metadata to MQTT messages and pass information between publisher, broker, and subscriber.
|
||||
/// The feature is very similar to the HTTP header concept.
|
||||
/// Hint: MQTT 5 feature only.
|
||||
/// </summary>
|
||||
public List<MqttUserProperty> UserProperties => _initialAuthPacket.UserProperties;
|
||||
|
||||
public async Task<ReceiveMqttEnhancedAuthenticationDataResult> ReceiveAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var receivedPacket = await _channelAdapter.ReceivePacketAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (receivedPacket is MqttAuthPacket authPacket)
|
||||
{
|
||||
return new ReceiveMqttEnhancedAuthenticationDataResult
|
||||
{
|
||||
AuthenticationData = authPacket.AuthenticationData,
|
||||
AuthenticationMethod = authPacket.AuthenticationMethod,
|
||||
ReasonString = authPacket.ReasonString,
|
||||
ReasonCode = authPacket.ReasonCode,
|
||||
UserProperties = authPacket.UserProperties
|
||||
};
|
||||
}
|
||||
|
||||
if (receivedPacket is MqttConnAckPacket)
|
||||
{
|
||||
throw new InvalidOperationException("The enhanced authentication handler must not wait for the CONNACK packet.");
|
||||
}
|
||||
|
||||
throw new MqttProtocolViolationException("Received other packet than AUTH while authenticating.");
|
||||
}
|
||||
|
||||
public Task SendAsync(SendMqttEnhancedAuthenticationDataOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
var authPacket = new MqttAuthPacket
|
||||
{
|
||||
ReasonCode = MqttAuthenticateReasonCode.ContinueAuthentication,
|
||||
AuthenticationMethod = AuthenticationMethod,
|
||||
AuthenticationData = options.Data,
|
||||
UserProperties = options.UserProperties,
|
||||
ReasonString = options.ReasonString
|
||||
};
|
||||
|
||||
return _channelAdapter.SendPacketAsync(authPacket, cancellationToken);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet;
|
||||
|
||||
public class MqttExtendedAuthenticationExchangeData
|
||||
public class MqttEnhancedAuthenticationExchangeData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the authentication data.
|
||||
@@ -0,0 +1,22 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
namespace MQTTnet;
|
||||
|
||||
public sealed class ReceiveMqttEnhancedAuthenticationDataResult
|
||||
{
|
||||
public byte[] AuthenticationData { get; init; }
|
||||
|
||||
public string AuthenticationMethod { get; init; }
|
||||
|
||||
public MqttAuthenticateReasonCode ReasonCode { get; init; }
|
||||
|
||||
public string ReasonString { get; init; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using MQTTnet.Packets;
|
||||
|
||||
namespace MQTTnet;
|
||||
|
||||
public sealed class SendMqttEnhancedAuthenticationDataOptions
|
||||
{
|
||||
public byte[] Data { get; init; }
|
||||
|
||||
public string ReasonString { get; init; }
|
||||
|
||||
public List<MqttUserProperty> UserProperties { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user