The CONNECT Packet contains Username and Password fields. Implementations can choose how to make use of the content of these fields. They may provide their own authentication mechanism, use an external authentication system such as LDAP or Oauth [sic] tokens, or leverage operating system authentication mechanisms.The spec also allows for client authentication through VPN or SSL. And also it seems inserting arbitrary credentials in the application payload as well.
An implementation might allow for authentication where the credentials are flowed in an Application Message from the Client to the Server.Separate from the interoperability challenge presented by so many different client authentication mechanisms, there is (to my mind) a more fundamental issue with MQTT's client authentication model.
There are both ClientID and Username params allowed on the CONNECT message. This would allow for separate identification of both the MQTT client and any user that that client was sending messages on behalf of. This seems appropriate - allowing for a single client to potentially represent different users over time. But there is only a single Password (or equivalent) parameter on the CONNECT and it appears to serve double duty for both authentication of the client and also any user.
Because there is only one Password parameter, it seems you can't authenticate both the client and a user simultaneously on the same CONNECT.
If you did need to authenticate both client & user simultaneously, it would seem you would need to do something like
- use client-authn SSL to authenticate the client & use the Password field for the user, or
- use the Password field for client & some application message param for the user (or vice versa?)
Choice is good except when it isn't.....
If MQTT allowed for a 'client_pwd' (name it what you will) to be paired with the existing Clientid parameter, and thereby distinguish between credentials for the client (client_pwd) and the user (Password), then the whole situation would be cleaner.
Even cleaner would be to define a new CONNECT field called 'access_token', and use that instead of forcing OAuth tokens into the existing parameters (which can be problematic as Paul discovered).
I couldn't encode the token as the password, because of the way Mosquitto and mosquitto_pyauth call my code. I ended up passing the token as the username instead. I need to look at the mosquitto auth plugin interface more deeply to see if this is something I can fix or I need help from Mosquitto for.