mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-17 09:43:05 +08:00
159 lines
7.7 KiB
C#
159 lines
7.7 KiB
C#
// 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.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using MQTTnet.Client;
|
|
using MQTTnet.Formatter;
|
|
using MQTTnet.Internal;
|
|
using MQTTnet.Packets;
|
|
using MQTTnet.Protocol;
|
|
|
|
namespace MQTTnet.Tests.Clients.MqttClient
|
|
{
|
|
[TestClass]
|
|
public sealed class Extended_Authentication_Tests : BaseTestClass
|
|
{
|
|
[TestMethod]
|
|
public async Task ReAuthenticate()
|
|
{
|
|
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
|
{
|
|
var server = await testEnvironment.StartServer();
|
|
|
|
server.ValidatingConnectionAsync += async args =>
|
|
{
|
|
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
|
|
{
|
|
// Just do a simple custom authentication.
|
|
await args.SendAuthenticationDataAsync(MqttAuthenticateReasonCode.ContinueAuthentication, cancellationToken: timeout.Token);
|
|
var clientResponse = await args.ReceiveAuthenticationDataAsync(timeout.Token);
|
|
CollectionAssert.AreEqual(clientResponse.AuthenticationData, Encoding.ASCII.GetBytes("TOKEN"));
|
|
|
|
var userProperties = new MqttUserPropertiesBuilder().With("x", "y").Build();
|
|
await args.SendAuthenticationDataAsync(MqttAuthenticateReasonCode.ContinueAuthentication, cancellationToken: timeout.Token, userProperties: userProperties);
|
|
|
|
args.ReasonCode = MqttConnectReasonCode.Success;
|
|
}
|
|
};
|
|
|
|
server.ClientReAuthenticatingAsync += args =>
|
|
{
|
|
|
|
return CompletedTask.Instance;
|
|
};
|
|
|
|
var client = testEnvironment.CreateClient();
|
|
client.ExtendedAuthenticationExchangeAsync += async args =>
|
|
{
|
|
await args.SendAuthenticationDataAsync(MqttAuthenticateReasonCode.ContinueAuthentication, Encoding.ASCII.GetBytes("TOKEN"));
|
|
|
|
var serverResponse = await args.ReceiveAuthenticationDataAsync(CancellationToken.None);
|
|
Assert.IsNotNull(serverResponse.UserProperties);
|
|
Assert.AreEqual("x", serverResponse.UserProperties[0].Name);
|
|
Assert.AreEqual("y", serverResponse.UserProperties[0].Value);
|
|
};
|
|
|
|
var clientOptions = testEnvironment.CreateDefaultClientOptionsBuilder().WithTimeout(TimeSpan.FromSeconds(10)).WithAuthentication("CUSTOM").Build();
|
|
await client.ConnectAsync(clientOptions);
|
|
|
|
await LongTestDelay();
|
|
|
|
await client.ReAuthenticateAsync();
|
|
|
|
await LongTestDelay();
|
|
|
|
var pingResult = await client.TryPingAsync();
|
|
|
|
Assert.IsTrue(pingResult);
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Use_Extended_Authentication()
|
|
{
|
|
var initialContextToken = Encoding.ASCII.GetBytes("initial context token");
|
|
var replyContextToken = Encoding.ASCII.GetBytes("reply context token");
|
|
var outcomeOfAuthentication = Encoding.ASCII.GetBytes("outcome of authentication");
|
|
|
|
using (var testEnvironment = CreateTestEnvironment(MqttProtocolVersion.V500))
|
|
{
|
|
var server = await testEnvironment.StartServer();
|
|
|
|
/*
|
|
Sample flow from RFC:
|
|
|
|
1. Client to Server CONNECT Authentication Method="GS2-KRB5"
|
|
2. Server to Client AUTH rc=0x18 Authentication Method="GS2-KRB5"
|
|
3. Client to Server AUTH rc=0x18 Authentication Method="GS2-KRB5" Authentication Data=initial context token
|
|
4. Server to Client AUTH rc=0x18 Authentication Method="GS2-KRB5" Authentication Data=reply context token
|
|
5. Client to Server AUTH rc=0x18 Authentication Method="GS2-KRB5"
|
|
6. Server to Client CONNACK rc=0 Authentication Method="GS2-KRB5" Authentication Data=outcome of authentication
|
|
*/
|
|
|
|
server.ValidatingConnectionAsync += async args =>
|
|
{
|
|
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
|
|
{
|
|
// 1.
|
|
if (args.AuthenticationMethod != "GS2-KRB5")
|
|
{
|
|
args.ReasonCode = MqttConnectReasonCode.BadAuthenticationMethod;
|
|
return;
|
|
}
|
|
|
|
// 2.
|
|
await args.SendAuthenticationDataAsync(MqttAuthenticateReasonCode.ContinueAuthentication, cancellationToken: timeout.Token);
|
|
|
|
// 3.
|
|
var clientResponse = await args.ReceiveAuthenticationDataAsync(timeout.Token);
|
|
CollectionAssert.AreEqual(clientResponse.AuthenticationData, initialContextToken);
|
|
Assert.AreEqual(MqttAuthenticateReasonCode.ContinueAuthentication, clientResponse.ReasonCode);
|
|
|
|
// 4.
|
|
await args.SendAuthenticationDataAsync(MqttAuthenticateReasonCode.ContinueAuthentication, replyContextToken, cancellationToken: timeout.Token);
|
|
|
|
// 5.
|
|
clientResponse = await args.ReceiveAuthenticationDataAsync(timeout.Token);
|
|
Assert.AreEqual(clientResponse.AuthenticationData, null);
|
|
Assert.AreEqual(MqttAuthenticateReasonCode.ContinueAuthentication, clientResponse.ReasonCode);
|
|
|
|
// 6.
|
|
args.ResponseAuthenticationData = outcomeOfAuthentication;
|
|
args.ReasonCode = MqttConnectReasonCode.Success;
|
|
}
|
|
};
|
|
|
|
var client = testEnvironment.CreateClient();
|
|
client.ExtendedAuthenticationExchangeAsync += async args =>
|
|
{
|
|
if (args.AuthenticationMethod != "GS2-KRB5")
|
|
{
|
|
Assert.Fail("Authentication method is wrong.");
|
|
}
|
|
|
|
// 2. THE FACT THAT THE SERVER SENDS THE AUTH PACKET WILL TRIGGER THIS EVENT SO THE INITIAL DATA IS IN THE EVENT ARGS!
|
|
Assert.AreEqual(MqttAuthenticateReasonCode.ContinueAuthentication, args.ReasonCode);
|
|
|
|
// 3.
|
|
await args.SendAuthenticationDataAsync(MqttAuthenticateReasonCode.ContinueAuthentication, initialContextToken);
|
|
|
|
// 4.
|
|
var serverResponse = await args.ReceiveAuthenticationDataAsync(CancellationToken.None);
|
|
CollectionAssert.AreEqual(serverResponse.AuthenticationData, replyContextToken);
|
|
Assert.AreEqual(MqttAuthenticateReasonCode.ContinueAuthentication, serverResponse.ReasonCode);
|
|
|
|
// 5.
|
|
await args.SendAuthenticationDataAsync(MqttAuthenticateReasonCode.ContinueAuthentication);
|
|
};
|
|
|
|
var clientOptions = testEnvironment.CreateDefaultClientOptionsBuilder().WithTimeout(TimeSpan.FromSeconds(10)).WithAuthentication("GS2-KRB5").Build();
|
|
await client.ConnectAsync(clientOptions);
|
|
}
|
|
}
|
|
}
|
|
} |