Creating and Using Client Certificates with MQTT and Mosquitto

Another popular way of authenticating clients is via client certificates and can be use as in addition or as an alternative to using user name and password authentication.

In cryptography, a client certificate is a type of digital certificate that is used by client systems to make authenticated requests to a remote server.

Client certificates play a key role in many mutual authentication designs, providing strong assurances of a requester’s identity. –Wiki

A client certificate identifies the client just like the server certificate identifies the server.

Normally certificates are created and distributed to each client that connects to the server/broker that requires them.

However you can share a client certificate between clients.

As with username and password authentication the broker dictates whether or not a clients need to supply a certificate.

You can use certificates in combination with username and password authentication.

Mosquitto Broker Configuration

The main two settings are:

  • require_certificates – Main setting tells client it needs to supply a certificate when set to true. Default false
  • use_identity_as_username– – When set to true it tells mosquitto not to use the password file but to take the username from the certificate (common name given to certificate when you create it). Default false
  • crlfile – You can create a certificate revocation file that is used to revoke a client certificate

Creating Self SIgned Client Certificates

The client and server must use the same CA (certificate Authority)  for the client and server certificates.

You create the client certificates using the same process as you used for creating a server certificate.

  1. Create a client key  don’t password protect.
  2. Create a client certificate request using the key.
  3. Use the CA key to sign the client certificate request from step 2.

Preparation –

You need an existing CA certificate and private key which you get when you follow the steps for creating your own self signed server certificate.

You need to use the same CA for the client certificates as the server certificate, and the broker needs to use SSL.

This is because  client certificates require an encrypted connection.

If you don’t have a CA certificate then you need create one using the following:

First create a key for the CA

Command is:  openssl genrsa -des3 -out ca.key 2048


Note: it is OK to create a password protected key for the CA.

Next:  Create a certificate for the CA using the CA key that we created in step 1

Command is:  openssl req -new -x509 -days 1826 -key ca.key -out ca.crt


If you have followed the tutorial on creating server certificates then your folder should look like the one below:


Step 1

The first step is to create a client private key.

The command is:

openssl genrsa -out client.key 2048

create-client key

Step 2

Next create a certificate request and use the client private key to sign it.

The command is:

openssl req -new -out client.csr -key client.key

You will be presented with a form that you need to complete.

The most important entry is the common name. This name can be used by the broker to indentify the client in place of a username.

Normally this certificate would be sent to a Certificate authority, but we are our own Certificate authority so we complete the request to create a client certificate

Step 3

Now we complete the request and create a client certificate. The command is:

openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 360


This is now what our directory looks like


Using Client Certificates

To use client certificates the client requires three files:

  • ca.crt – The Certificate authority certificate
  • client.crt – The client certifcate file
  • client.key – The client private key

Publishing using Mosquitto_pub tool

The command is:

mosquitto_pub --cafile C:\ssl\ca.crt --cert C:\ssl\client.crt --key C:\ssl\client.key -d -h -p 8883 -t test -m "hello there"


Note: You need to use the server name that is on the server certificate. If I use the IP address instead I get this error.


Publish Using Python

If you use Python you need to set the TLS settings  using:


Publish Using Node-Red

On Node red you need to enable the SSL/TLS option in the broker settings.


and then upload the client files as shown in the screen shot below:


Mosquitto Broker Connection

When the client connects to the broker and the use_identity_as_username is true then this is what you see:



Example Mosquitto configuration file:

port 1883
log_type error
log_type notice
log_type information
log_type debug
#allow_anonymous false
#password_file /etc/mosquitto/pass.txt
#Extra Listeners
listener 8883
#ssl settings
cafile /home/steve/mos/certs/ca.crt
keyfile /home/steve/mos/certs/server.key
certfile /home/steve/mos/certs/server.crt
#client certifcate settings
require_certificate true
use_identity_as_username true

Terms Used

CA= Certificate Authority
Private Key = An encryption key that isn’t shared and needs to be stored securely
Public Key= An encryption key that is shared and doesn’t needs to be stored securely.
Certificate Request = An application for a certificate made to a certificate authority. Like a passport application

Shell Scripts

To save you typing I’ve created two Linux shell scripts that run the commands and create server and client certificates and keys as in this tutorial and the server certificate tutorial.

Related Tutorials

Please rate? And use Comments to let me know more
[Total: 8   Average: 5/5]


  1. Hi, Steve thx for this post 🙂

    i have a problem here with my project, im using raspberry pi3b+ which has the broker and the publisher, my configuration for broker is:

    pid_file /var/run/
    listener 8883
    #allow_anonymous true
    connection_messages true
    include_dir /etc/mosquitto/conf.d
    cafile /etc/mosquitto/ca_certificates/
    keyfile /etc/mosquitto/certs/broker.key
    certfile /etc/mosquitto/certs/broker.crt
    tls_version tlsv1
    protocol mqtt
    #require_certificate true
    #use_identity_as_username true
    #password_file /etc/mosquitto/pwfile

    the publisher is in raspberry pi and the subscriber i want to run it in other machine with ubuntu, the code for the publisher that i use is this

    publish.single(‘BPM’,”%d” % BPM,hostname=’′,port=8883,tls={‘ca_certs’:”/etc/mosquitto/ca_certificates/”})

    the subscriber has the next code:



    i choose for CA certificate and the same to sign client and server certificates, and its working good if all the scripts publisher and subscriber are in raspberry, good comunication with tls, but when i move the subscriber to other machine with ubuntu it produced this error:

    ssl.SSLCertVerificationError: [SSL: Certificate_verify_failed] IP address mismatch, certificate is not valid for ‘’. (_ssl.c:1108)

    the curious thing is i tried mosquito_sub -h -p 8883 –cafile /PATH -m “hello world” -t test
    and its working fine the message that i send from raspberry to other laptop with ubuntu it received properly, but when i tried to put the subcriber in script the error appear, i use python 2.7, i tried too with python 3.8 but the error continue appearing.

    i really apreciate some ideas to try 🙂


    1. Hi
      Looks like a ca name mismatch try using in insecure option to verify this.
      You alos seem to be mixing publish with subscribe commands
      mosquito_sub -h -p 8883 –cafile /PATH -m “hello world” -t test
      Assume was a typo.
      Also It looks line on the subscribe side you are using client certificates if so remove them and try juts using SSL

  2. Hi Steve! nice post btw. I tried this and could not make it work.

    I created a CA key and cert, and also server key and cert and could enable a secure TLS connection, now using the same CA key and following this steps I’m getting the following errors:

    Client side: ssl3_read_bytes:tlsv1 alert unknown ca
    Server side: tls_process_client_certificate:certificate verify failed

    My .conf file has a listener defined as follows:

    # =================================================================
    # MQTT mutual-authentication
    # =================================================================
    listener 8884
    protocol mqtt
    capath /mosquitto/data/ca.crt
    keyfile /mosquitto/data/server.key
    certfile /mosquitto/data/server.crt
    require_certificate true

    I also tried using the use_identity_as_username flag

    any clues? thanks!

      1. Thanks for the quick reply.

        Indeed, I’ve used your scripts with the same result, I’m deploying everything to a docker container using the eclipse-mosquitto official image (latest version).

        I have also tried using the official documentation: and the problem remains.

        If you have any clues please let me know, I’ll keep on trying to make it work and if I’m successful with this I’ll post my results!

        Thanks again, and sorry for bothering you.

          1. tried in 2 different mac computers and having the same problem, where are you storing the broker certificates ? I’m using a fixed folder should I use some location inside /etc/ ? do you happen to have a full broker config with certificates to share?

            I’m using to test it now, but would love to have something locally and not depend on any 3p.

            Thanks again,

          2. The best solution is to install a local mosquitto broker. If you don’t have one then I will configure one on my network and send you the can so you can test.

  3. Hi, Thanks for the great article and tutorial.
    We’re using Mosquitto in an enterprise environment, and we are wanting to move to SSL encrypted traffic.
    We are using Active Directory and have our own domain-based CA.
    Is there a way to get Mosquitto broker to leverage somehow this infrastructure or integrate with it in some way ? All the tutorials are based on using OpenSSL to be ‘your own CA’ and self-sign, but we’ll be looking at managing up to 100 separate brokers and managing the certificates in this way will be an arduous task.
    Any pointers would be greatly appreciated !

    1. David
      You can use any CA certificates on mosquitto so you can generate them in AD. However you can’t distribute them to mosquitto using Active directory.
      Take me back a bit as I used to train Active directory and windows 2000 but stopped in about 2003 so I guess it has moved on a lot since then.

  4. Steve,

    This is a lot to take in and your guidance has helped, but there’s one tough challenge here: how to make a cert for a TLS connection when you’re just making clients and using someone else’s broker server. In my case that’s CloudMQTT, whose docs leave much to be desired:

    Do I need their server cert (if I can get it) to make my client certs?


    1. Hi
      Interesting question and I will look into it. However Cloudmqtt don’t say that they support client certificates as far as I can see.

  5. Hi Steve,

    Thanks for a great article.

    I am trying to figure out what happens in the following scenarios after a client (for example node-red) connects using client & server certificates and subscribes to a topic which they have read permission (controlled by acl_file).

    1. Client certificate is revoked or expires. Would the client be disconnected?
    2. Read permission on the topic removed for a user. Does a client for that user stop getting messages on that topic?


    1. Hi
      There is no checking for revoked certificates so nothing would happen.
      For the ACL then the client would not longer receive messages on that topic.

    1. I believe you can use a single client certificate for all clients but it isn’t recommended and so if you use client certificates then each client should have its own.

      1. I’m using “my-ca.crt” for connecting mqtt , and in mqtt.config file i gave “cafile /etc/mosquitto/certs/my-ca4.crt”. So for every certificate i generate should i also change the .config file?

        1. The config file on mosquitto stays the same. Each client needs to use it’s own client certificate there is no change needed on the broker other than to configure it to use SSL and client certificates.
          This is the relevant part of the file
          #ssl settings
          cafile /home/steve/mos/certs/ca.crt
          keyfile /home/steve/mos/certs/server.key
          certfile /home/steve/mos/certs/server.crt
          #client certifcate settings
          require_certificate true
          use_identity_as_username true


  6. Hi Steve, Thanks for all this information. It has been most useful in the setup and configurations that I have used. There is one puzzle and I cannot get around it. The publishing client requires only Client certificate and key and doesn’t have a placeholder for the server certificate. Is there a way to have such a configuration. So if I use the command above as a template, instead of [[mosquitto_pub -h -p -t -m –cafile mqttproxy-ca.crt -u -P -d –cert mqttproxy-ca.crt –key mqttproxy-ca-pkcs8-withoutpass.key]], I have to use [[mosquitto_pub -h -p -t -m -u -P -d –cert mqttproxy-ca.crt –key mqttproxy-ca-pkcs8-withoutpass.key]]. I am using MQTT proxy for Confluent Kafka as the broker.

  7. Hi Steve, you have been inspiritaion in many aspects, now I am securing all my devices . But I am facing an issue. mosquitto broker is working fine in user&pass , and TLS config on port 8883, tested from paho-eclipse websocket online app. So Iam 100% sure is working, also locally with this command : mosquitto_pub -h -t test -m “hello again” -p 8883 –capath /etc/ssl/certs/ -u “” -P “” -d , but I am stuck with certificates. (I am using wildcard one for mosquitto broker) but which is the the one that mosquitto_pub is using from this path “/etc/ssl/certs/” I see 273 listed there. Thanks a lot in advance

    1. Hi
      It will use the one that corresponds to the CA on the broker as I understand it just the same way as when you access a website your don’t know the CA of the website so your browser has to search in the store for a matching one.

    1. Yes I’m sure it is but I don’t have the time to do that at the moment if yoy develop one let me know

  8. Hi Steve, I setup my mosquitto-tls following your tutorials.
    CA :
    openssl genrsa -des3 -out ca.key 2048
    openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
    Common Name (eg, fully qualified host name) []

    Server :
    openssl genrsa -out server.key 2048
    openssl req -new -out server.csr -key server.key
    Common Name (eg, fully qualified host name) []
    openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360

    Client :
    openssl genrsa -out client.key 2048
    openssl req -new -out client.csr -key client.key
    Common Name (eg, fully qualified host name) []:device1
    openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 360

    mosquitto.conf :
    port 1883
    listener 8883
    cafile /mosquitto/certs/ca.crt
    certfile /mosquitto/certs/server.crt
    keyfile /mosquitto/certs/server.key
    tls_version tlsv1.2
    use_identity_as_username true

    I use MQTT.fx to connect to my broker using ca.crt, client.crt, client.key. But getting following error

    2020-03-30 12:13:09,793 ERROR — MqttFX ClientModel : Error when connecting invalid key format
    at ~[?:1.8.0_181]
    at ~[?:1.8.0_181]

    at [?:1.8.0_181]
    Caused by: invalid key format
    at ~[?:1.8.0_181]

    2020-03-30 12:13:09,796 ERROR — MqttFX ClientModel : Please verify your Settings (e.g. Broker Address, Broker Port & Client ID) and the user credentials! invalid key format

    at [?:1.8.0_181]
    Caused by: invalid key format
    at ~[?:1.8.0_181]

    Any idea what is wrong with my setup ?

    1. No I have used MQTT.fx.
      I would go back a step and try it first just using SSL and no client certificates and get that working after that introduce the client certificates.
      If you get nowhere then use the ask steve page and get it touch and you can then send me your certs and keys and I will try them. I can also send you a python script to try.

      1. I have two ports 1883 & 8883. I was able to connect to port 1883 with no SSL/TLS. Getting above error when I try to connect to port 8883 with SSL/TLS.

        1. Roy
          Have you tried just using SSL and note client certificates. Also have you tried the mosquitto_pub tool. It is also worth trying another machine in case there is a problem with the SSL version.
          Send me your certs and keys and I’ll try them.

  9. Hi there,

    Anyone has configured successfully the client certificate for homeassistant mqtt?
    I am using a mosquitto broker and hass version 0.105.2.
    This is the message I get:
    Invalid config for [mqtt]: not a file for dictionary value @ data[‘mqtt’][‘client_key’]. Got ‘client.key’.

    with this configuration.yaml:
    port: 8883
    certificate: /etc/mosquitto/ca_certificates/ca.crt
    client_key: client.key
    client_cert: /etc/mosquitto/certs/client.crt
    tls_version: ‘auto’
    # tls_insecure: true
    # username: hass.client

    It is working perfectly when I am subscribing and publishing with mosquitto clients, from ubuntu.
    In the broker I have enabled the “require_certificate” option.
    But given the error, I guess the mqtt module from hass seems not to accept key file format or similar issue.
    I have already tried to change the permissions, and the issues remains…
    Any idea?

    Thanks a lot!

    1. Already fixed. It was an issue with the read permissions of the key. I change them once, but I regenerate the key… Stupid me 🙂

  10. Hi Steve,

    Thanks for the great article! Helped me immensely. The client I am using requests only the CA certificate (ca.crt) and the client certificate (client.crt) and doesn’t ask for the client key (client.key). Should this be possible? It is asking for the certificates in DER format so I have converted them using openSSL but the system still doesn’t work. Other clients I have set up using MQTT.fx have worked OK when using the PEM formatted certs and keys is all good, however when using the DER formatted keys etc Mosquitto reports the following when trying to connect (same message when using either client):

    1580938430: New connection from on port 8883.
    1580938430: OpenSSL Error: error:1417C0C7:SSL routines:tls_process_client_certificate:peer did not return a certificate
    1580938430: Socket error on client , disconnecting.

    Can you shed any light on this? Do I need to create all keys (not just client) in the DER format?

    1. Hi
      As far a I understand it you need the client key the format shouldn’t matter. If you use the ask steve page to contact me then you can send me all of the files (sever and client) by email and I’ll try them on my broker.

  11. Hi, Steve
    Good article!
    I have setup mutual authentication with following configurations and they works well for my client using MQTT.fx.

    port 1883
    allow_anonymous false
    require_certificate true
    use_identity_as_username true
    cafile ~/root.crt
    certfile ~/server.crt
    keyfile ~/server.key

    The question is I do not see mosquitto server have a configuration method can check whether the client’s CN is in a local database for allowing connection. As you can see I already set allow_anonymous to false, although the client is signed by the CA certificate, it is still a unknown client to me when it is not in the ‘database’.
    The acl_file can limit the Pub/Sub permission of a specific username, but it can’t deny a client not in list.

    1. Just to clarify.
      You are trying tp limit access using certificate common name?
      Can you send me the acl you are using and I’ll try it.

      1. I did not build a ACL file. After checked ACL file syntax, it looks like it only be used to limit read/write permission to topics. It should be easy to define a ACL to not allow a user to pub/sub to any topic. But I want that user to be refused during connection. By checking it’s username (CN, as I defined use_identity_as_username)

        1. Hi
          It looks to me that the client name can be used for ACL control but not authentication as the certificate is doing that job.
          It is something I haven’t checked but reading the config file data seems to indicate that.

  12. Hi Steve,

    Thank you for this wonderful article. I’m trying to achieve the same flow using Nginx as a load balancer and HiveMQ enterprise MQTT broker. The point is to Terminate SSL at the load balancer and also use client certificates for authentication. But the problem I’m facing is that the client certificates, even when changing the name of the client, works. Nginx authenticates the client irrespective of what the client ID is. Am I correct in assuming that this shouldn’t be the case? Only a client whose ClientID matches the FQDN string passed during its certificate creation be authenticated?

    1. Sorry but I’ve never used nginx with MQTT. However I suspect that nginx doesn’t cat about the client certificates as the authentication should be done on the broker.

  13. Hi Steve,
    Very well explained!!
    I have a question,
    ca.crt – The Certificate authority certificate
    client.crt – The client certifcate file
    client.key – The client private key
    While publishing a message, we are using below:

    Why should we send private key (client.key) in the handshake? That is to be stored securely right?
    Can you pls explain me in detail.

    Also We have an assignment:
    We are creating self-signed certificates using “openssl rsa” in the middleware(in our project). We’ve generated a cafile, certfile and privatekey and assigned it to vernemq broker(hosted in a cloud platform).

    Later we created multiple clients, each client is assigned a certfile and private key. Anyways cafile would be the same. Now these clients need to publish messages to the broker.
    We have configured in the message broker config file as below:
    listener.ssl.require_certificate=on and listener.ssl.use_identity_as_username=on

    How can the clients publish messages to the broker using their client certificates and how would the broker validate if it is a valid client? How can we do asymmetric key encryption?
    Can u pls describe any approach for this?

    Thanks in advance.

      1. Hi Steve,
        I have a question.
        I’m using a vernemq message broker. I have a client in VM which is trying to connect to the message broker using certificates. (Self-signed).
        I used the same CA in generating certificates for both the message broker and the client.
        CN for Vernemq message broker is “message broker”
        CN for client in VM is “send-data”
        client is written in nestjs( nodejs framework)
        Now, when i try to make a connection from the client to the message broker.

        It says “Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate’s altnames: Host: is not cert’s CN: messagebroker”

        Any idea? Why am i getting this error and how to resolve it?

        Sri Durga

        1. I can only assume that the certificate common name doesn’t match the name that is being used by the server it is being used on. Most clients have an insecure option which bypasses this check. If that works then it more or less proves the name/IP mismatch.

  14. Hi Steve.
    First of all thank you for all of these information, but I want to know what is the purpose of these client step. What will happen if we use only ca.crt but not client.crt and client.key? Thank you in advance…

    1. Using the ca.crt only on the client is the way most clients will be configured. This mode is effectively the same mode as you use on a web browser when accessing a secure site.
      You only need client certificates if you want to use them to authenticate the client usually in place of a username/password authentication.
      DEoes that make sense?

      1. Thank you for a quick response 🙂
        Now. I am trying to use client certificate but I am facing with the error:
        ssl.SSLError: [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:661)
        when I try to connect. What can be the reason of this ? Btw
        my tls_set code is —-
        Is there any error here?
        Thx in advance again …

          1. My original conf file is like :
            port 1883
            listener 8883
            cafile /home/pi/Security/ca.crt
            keyfile /home/pi/Security/server.key
            certfile /home/pi/Security/server.crt

            I’m sorry for deleting by mistake.

          2. You also need these lines when using client certificates
            #client certifcate settings
            require_certificate true
            use_identity_as_username true

        1. Hi Steve,
          Thanks for this awesome blog post!
          I am facing one challenge… I have a device certificate (device.pem) ,(devicekey.key) and secret key from the available device in cloud but I am confused which certificate do I need to use in tls_set().
          I have tried with eclipse paho tool and I have used cacerts (available in jre folder) with password “changeit” and devicekey.key as keystore and device secret as password.
          Please help and let me know if any other information is required.

          1. Hi
            You need the Ca certificate the client certificate and the client key


          2. Hi Steve,
            Thanks for the help.
            I have provided all the certificates (ca.crt, client.crt, client.key) in tls_set but when I am trying to execute client.connect(broker,8883,timeout) I am getting [SSL:CERTIFICATE_VERIFY_FAILED] certificate verify failed : unable to get local issuer certificate (_ssl.c:1056)
            Trace back: selfobj.do_handshake()

            Please help !


          3. This is usually caused by the common name on the server certificate being different to the name you use when you access the broker. If you use the insecure option in the client then it overrides the check and it should work. If it does then it is a clear sign that you have a name mismatch

          4. Hi Steve,
            Thanks for the reply!
            Please help me in solving my confusion. What will be the use of the device certificate then if i will be using the certificated generated by me using openssl?
            I tried with the “MQTT.fx” and enabled “TLS/SSL” and “selected self sign certificates in keystore” option.
            my keystore file : cacerts -> got from jre folder where java is installed
            client keystore file : client.key
            client keystore is generated by “openssl pkcs12 -export -in certificate.pem -inkey certificate.pem -out client.ks”
            client keystore password : password from device certificate (generated automatically )
            client keypair password : same as client keystore password.

            so my confusion is what will be the values in tls_set parameter() ?

            Thanks for the help!

          5. Hi
            Client certificates are used instead of username/password authentication.
            Client certificates are considered more secure than username/password encryption but they are more difficult to set up and less well understood.
            However they need an encrypted connection to work and therefore the connection must use SSL.
            Does that make sense

Leave a Reply

Your email address will not be published. Required fields are marked *