rabbitmq / rabbitmq-server

Open source RabbitMQ: core server and tier 1 (built-in) plugins
https://www.rabbitmq.com/
Other
12.27k stars 3.91k forks source link

Web STOMP: consider periodically re-evaluating JWT token #8295

Open michaelklishin opened 1 year ago

michaelklishin commented 1 year ago

Is your feature request related to a problem? Please describe.

See https://github.com/rabbitmq/rabbitmq-server/discussions/8293 for background.

Web STOMP, unlike some other protocols, evaluates JWT token expiration only in a couple of cases:

  1. When a client connects
  2. When a client issues a SUBSCRIBE frame

With some other protocols, this check is performed a more often for various reasons, although things generally won't be very different for "passive" consumers (that never publish or do anything beyond handling inbound deliveries).

Describe the solution you'd like

Checking for token expiration on every operation will be wasteful. 99.99% of the time the token will be valid.

Alternatively, plugins could periodically (say, once a few minutes) tell all connections to re-evaluate their JWT token and self-close if it's expired. This can be expensive with a lot of connections, so the interval should be at least 1m.

Describe alternatives you've considered

No response

Additional context

No response

thomas-rudlof-bl commented 1 year ago

Since the token tells you when it expires, you don't have to re-validate the token on every operation or every couple of minutes. I had the impression, that sending stops working as soon as the token expires. How is sending prevented (efficiently) after token expiration? Could this work in the other direction too?

It would be cool, if the connection would stop working - and even cooler, if the stomp client could send a special frame with a new access token before this happens!

But I understand, that this might all be too complex - in which case it would be nice to update the description of the Stomp Plugin accordingly.

MarcialRosales commented 1 year ago

@thomas-rudlof-bl The stomp protocol does not explicitly say that there can only be one CONNECT frame per connection. So, in theory, the client could send another CONNECT frame, with the new token, before the current token expires.

With regards token validation, RabbitMQ always check token validity on every operation. That is why the sender quickly detects that the token has expired. With regards the subscription, most likely, RabbitMQ will check the token before sending the next message. Which means, the subscription may not be closed as soon as the token expires if there are no messages for the subscription.

michaelklishin commented 1 year ago

By "re-evaluation" I mean checking with the token. Depending on how the token is stored internally, it may or may not be cheap.

Running a set of token validation steps for every operation, including a published message or delivery, is an overkill since 99.99% of the time the answer will be "your token is still valid". Hence the periodic connection self-evaluation idea.

thomas-rudlof-bl commented 1 year ago

With regards token validation, RabbitMQ always check token validity on every operation. That is why the sender quickly detects that the token has expired. With regards the subscription, most likely, RabbitMQ will check the token before sending the next message. Which means, the subscription may not be closed as soon as the token expires if there are no messages for the subscription.

@MarcialRosales : Actually, you can still receive messages way after token expiration. I have the feeling, when forwarding a message to a client, the validity of the token of that client is not checked. It seems to be checked only, when the client subscribes. It is also checked, when the client sends a message.

thomas-rudlof-bl commented 1 year ago

@michaelklishin : I totally agree. An alternative to periodic checks might be to store (a reference to) the tokens and the connection in a sorted set, ordered by token expiration, and set a timer, that fires when the next token expires. Of course, you might have to update the timer, if a new connection with shorter expiration comes in. In that way, checking the token expiration is only a burden on top of establishing and terminating a connection but does not impact sending and retrieving messages.