moscajs / mosca

MQTT broker as a module
mosca.io
3.2k stars 508 forks source link

Client connection closed if publish is not authorized #596

Open gotev opened 7 years ago

gotev commented 7 years ago

Scenario

A client authenticates with Mosca server (2.2.0) and then tries to publish a message on a topic on which it does not have access. The publish does not succeed and the client connection is closed by the server.

By reading the MQTT specification I've seen this:

If a Server implementation does not authorize a PUBLISH to be performed by a Client; it has no way of informing that Client. It MUST either make a positive acknowledgement, according to the normal QoS rules, or close the Network Connection [MQTT-3.3.5-2].

By digging in the Mosca code I've seen that the client connection gets closed if the authorization is not granted and there's not a way to return an ack without actually performing the publishing of the message. I think it will be useful to have the possibility to not disconnect the client if a publish fails due to authorization. Simply return a puback without publishing the message.

mcollina commented 7 years ago

@gotev I do not understand, the spec says to close the connection.

gotev commented 7 years ago

From the specifics, it's said that if the publish is not authorized, the server must send a positive ack or close the connection. At the moment it's not possible to send a positive ack

mcollina commented 7 years ago

The positive ack is in the form of a PUBACK if QoS=1. It's sent automatically if the authorization succeed.

RobertoBiundo commented 7 years ago

I think he has the same question as me. As far as i know, mosca complies with the specification. And that is fine. But, is there a way to deny a publish to a topic without closing the connection and still let the client know that the publish was denied.

Example. A user sends a message to a topic, if a certain condition is met by the business logic the message passes (the message complies with an internal protocol for example, or bandwidth limitation). Then the client sends a second message, but that message will be denied (for X reason). Is there a way to tell the client, this publish was denied, here is the reason, without closing the connection?

I tried doing this with with server.published and server.authorizePublish

authorize closes the connection and thats ok. published on the other had has a callback. If i call callback("Error message", false); the message is not published, but the client doesn't receive the error message. (I'm not 100% sure of this) for a test i used mosquito_pub with debug mode, and i was not able to see the message. Not sure if this a thing with mosquitto or mosca.

mcollina commented 7 years ago

Is there a way to tell the client, this publish was denied, here is the reason, without closing the connection?

no. there is no way the error can reach the client, it's the MQTT protocol.

RobertoBiundo commented 7 years ago

Ok, ill do it then by publishing a message back to the client on a topic with an error message. Thanks

RobertoBiundo commented 7 years ago

My question now is. If in the authorisePublish i detect that i don't want that message and that i will drop de connection. Is there any way to tell the client why? Example. Publish a message to a topic and then close the connection Will he get the message before the connection is closed?

mcollina commented 7 years ago

@RobertoBiundo no.

RobertoBiundo commented 7 years ago

Is there any way to skip the queue and send the message using the socket directly and then close the connection?

RobertoBiundo commented 7 years ago

Since this works over TCP/IP the message should arrive to the client. I know that i have to modify the broker to achieve this. But do you think is posible in an easy way?

mcollina commented 7 years ago

Mosca does not have that capability, but Aedes do https://github.com/mcollina/aedes.

See https://github.com/mcollina/aedes#clientpublishmessage-callback.

RobertoBiundo commented 7 years ago

Ahhh!, nice!...nice.... Thank you very much !