dotnet / MQTTnet

MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker). The implementation is based on the documentation from http://mqtt.org/.
MIT License
4.46k stars 1.06k forks source link

Validate client certificate in the broker #644

Open alessandro23pellizzari opened 5 years ago

alessandro23pellizzari commented 5 years ago

Hi,

I wanted to be able to verify the identity of the client on the broker. As things are it seems that this is not supported. While searching for a solution, I saw this post that was related: https://github.com/chkr1011/MQTTnet/issues/136 and it seems that it could be possible to add the X509Certificate to the validation context. In my case, it would be enough to expose this certificate so from that I could implement a custom function that checks if this X509Certificate certificate is valid or not.

Could you do that? Thanks a lot in advance.

fogzot commented 5 years ago

I worked on that but without an Windows machine to develop/test the UWP part of the patch I preferred to not submit it. We're using my branch in production and it is still on my to-do to port the code to 3.x and submit a pull request. You can find some code here:

https://github.com/fogzot/MQTTnet/tree/feature-client-certificate

chkr1011 commented 5 years ago

I released a new nuget 3.0.3-rc2. Please let me know if this version works. The certificate is now exposed to the Client Connection Validator.

alessandro23pellizzari commented 5 years ago

Sorry for the late reply. I have tried to access the certificate in the Client Connection Validator. It is accessible but it seems to always be null. I'm using the MqttClient and I set the certificate in the Certificates parameter of the MqttClientOptionsBuilderTlsParameters. It seems that the certificate is received by the Mqttnet.Server because by setting TlsEndpointOptions.ClientCertificateRequired to true the connection is established successfully, while if the client does not use a certificate, the connection is not established, as one would expect. It could be that I'm missing something?

bcrosnier commented 5 years ago

Are you using ASP.NET Core WebSockets and Kestrel?

Kestrel does not enable Client certificates by default (so no matter what you send, the MQTTnet middleware will never receive any certificate). I just encountered this issue.

You can enable Client certificates using the Kestrel defaults in your Program.cs by configuring the HttpsConnectionAdapterOptions - it looks like something like this on my end:

public static IWebHostBuilder CreateWebHostBuilder( string[] args ) =>
    WebHost.CreateDefaultBuilder( args )
        .ConfigureKestrel( ( context, options ) =>
        {
            options.ConfigureHttpsDefaults( httpsOptions =>
            {
                httpsOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate;
                // TODO: VALIDATE CERTIFICATE BELOW INSTEAD OF RETURNING TRUE
                httpsOptions.ClientCertificateValidation = ( certificate2, chain, arg3 ) => true;
            } );
        } )
        .UseStartup<Startup>();

If you have already a UseKestrel() somewhere, you can also use it inside.

You'll also need the Microsoft.AspNetCore.Server.Kestrel.Https NuGet package if you don't already have it.

If you use IIS or Azure App Service, you will have to enable the relevant options with each.

After enabling Client certificates in Kestrel, I can now see client certificates inside my IMqttServerConnectionValidator.

LouisCPro commented 4 years ago

Hi,

Can you provide us with an update on this topic ?

I use .NETFramework and cant use Kestrel, and I have the same problem. I need to identify my clients certificates as valid with the one stored on broker side.

Thanks for your feedback and code sample.