How to force disconnect of STOMP subscriptions

1,586 views
Skip to first unread message

Brad Wood

unread,
Dec 29, 2020, 12:59:34 PM12/29/20
to rabbitmq-users
Cross posted from Slack #usage-questions channel.

I'm using Rabbit with the STOMP plugin and HTTP backend auth for websocket pushes and it's working great.  I've noticed that once a stomp client in the browser subscribes to a topic and starts receiving messages, the authorization is not re-checked every time a message goes out.  The app I'm working on changes permissions throughout the day and a topic a user subscribed to in the morning may not longer be accessible to them in the afternoon.  How can I prevent a browser being left open all day from still listening to messages on a topic they no longer have permissions to?  Is the auth re-checked eventually, or is there a way to force the server to disconnect users who no longer are authorized or can the client simply stay subscribed forever? 

Thanks!

~Brad 

Wesley Peng

unread,
Dec 29, 2020, 9:43:06 PM12/29/20
to rabbitm...@googlegroups.com
Hi

This is the third party authentication issue, nothing about rabbitmq itself.
For the third auth mechanism, there is generally a timeout value for the token. When TTL expires, the token should be dropped.

Thanks


--
You received this message because you are subscribed to the Google Groups "rabbitmq-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rabbitmq-user...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rabbitmq-users/ae37a17f-e9b0-4101-a3b4-a4714964d06bn%40googlegroups.com.

Brad Wood

unread,
Dec 30, 2020, 12:56:44 AM12/30/20
to rabbitm...@googlegroups.com
Thanks for attempting to help Wesley, but you've misunderstood the question.  I'm not talking about the backend auth (HTTP in this case).  I'm talking about the fact that once a STOMP subscription is made, the browser can continue to receive messages on that web socket connection and rabbit will not ask the backend auth again if the user still has read access to the topic-- it just keeps sending messages.  My auth mechanism can't influence this if Rabbit isn't asking it!

Now it also seems there's a chance that when you say "third party authentication", you're referring to the JS STOMP library that I'm using in the browser.  But this makes no sense either.  I would never put security in the hands of the browser, where a malicious user could simply create a web socket connection of their own with no TTL.  No, this would need to be enforced on the rabbit side of things to occasionally check if the subscriber still read access to the topic before continuing to send messages.  Rabbit already hits my auth mechanism (HTTP API) every time the browser publishes a message to stomp.  But from my testing, the topic permissions are only checked once when the subscription is made to receive messages. 

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 



You received this message because you are subscribed to a topic in the Google Groups "rabbitmq-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/rabbitmq-users/qZx62Kf9k6w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to rabbitmq-user...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rabbitmq-users/CAOZE12pSYq6XzkXG%3D7FRm2BqatJxuXn9K9YfJskUZeTEcueUAw%40mail.gmail.com.

Brad Wood

unread,
Dec 31, 2020, 11:57:11 AM12/31/20
to rabbitm...@googlegroups.com
Anyone else want to take a crack at this question?

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 


Brad Wood

unread,
Jan 4, 2021, 12:48:40 PM1/4/21
to rabbitm...@googlegroups.com
Anyone else want to take a crack at this question? 
 
Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 



Luke Bakken

unread,
Jan 4, 2021, 2:33:28 PM1/4/21
to rabbitmq-users
Hi Brad,

Please don't bump your messages. The people who assist on this mailing list try to do so within a week.

RabbitMQ does not "re check" authorization once a connection has been established because of the performance implications.

In your case one option would be to enumerate the open connections and force-close them using the HTTP API when permissions change. If your STOMP connection has a unique name you should be able to close just the one connection. Your STOMP applications would then re-establish their connection and authorization would happen again.

Thanks,
Luke

https://rabbitmq.slack.com/archives/C1EDN83PA/p1609264098404300

Brad Wood

unread,
Jan 4, 2021, 3:35:03 PM1/4/21
to rabbitm...@googlegroups.com
Please don't bump your messages. 

Apologies.  It had been 6 days since the last reply and 4 days since I had last said anything, so it seemed like a reasonable time to reply again.  I manage several open source mailing lists myself and I know how easily messages can get forgotten about.

RabbitMQ does not "re check" authorization once a connection has been established because of the performance implications. 

From my testing, this is not an entirely true statement.  Rabbit does consult the back end auth every time the STOMP connection publishes a message to rabbit.   It only seems to have the behavior of not re-checking when delivering messages to a subscription.  I do realize there may be some technical difficulties of when to trigger a re-check, but there does seem to be a precedent in place for not 'remembering' auth in some cases.  I don't even need real time action here, I'd be happy if rabbit would just re-auth open STOMP subscriptions every hour or so.   As far as performance, I'm using the cached back end auth to wrap my HTTP backend auth, so the performance implications are minimalized.  How would I go about suggesting this as a formalized enhancement request?  I just sold a client on using Rabbit and when I told them it would leave STOMP subs open for all time so long as the user never closed their browser and never check them again, they looked at me funny  :)

In your case one option would be to enumerate the open connections and force-close them using the HTTP API when permissions change. 

This is an interesting idea.  To be clear, is this a feature available via the Java SDK, or are you referring to the HTTP API that is exposed via the management plugin?

If your STOMP connection has a unique name you should be able to close just the one connection.  

How would I go about determining that?   I am using a unique username for each connection if that's what you mean.  Or better yet, if you have a handy link to the docs in question, I can dig around there for answers.

Your STOMP applications would then re-establish their connection and authorization would happen again. 

Got it-- the stomp.js I'm using does have automatic reconnection that I've tested. 

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 


--
You received this message because you are subscribed to a topic in the Google Groups "rabbitmq-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/rabbitmq-users/qZx62Kf9k6w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to rabbitmq-user...@googlegroups.com.

Brad Wood

unread,
Jan 4, 2021, 4:20:41 PM1/4/21
to rabbitm...@googlegroups.com
I answered one of my questions in regards to docs for the HTTP API I assume is being suggested here:


The rest of my questions still stand.

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 


Luke Bakken

unread,
Jan 4, 2021, 5:41:11 PM1/4/21
to rabbitmq-users
Hi Brad,

RabbitMQ never checks auth when delivering a message to a consumer who has subscribed to a queue via basic.consume (which is what a STOMP subscription does under the hood). By that time it is assumed that the client has authenticated successfully and while the consumer is active no further checks are necessary. This applies to all protocols since all piggyback on AMQP and AMQP does not re-auth for message delivery.

It only seems to have the behavior of not re-checking when delivering messages to a subscription.  I do realize there may be some technical difficulties of when to trigger a re-check, but there does seem to be a precedent in place for not 'remembering' auth in some cases.  I don't even need real time action here, I'd be happy if rabbit would just re-auth open STOMP subscriptions every hour or so.   As far as performance, I'm using the cached back end auth to wrap my HTTP backend auth, so the performance implications are minimalized.  How would I go about suggesting this as a formalized enhancement request?  I just sold a client on using Rabbit and when I told them it would leave STOMP subs open for all time so long as the user never closed their browser and never check them again, they looked at me funny  :)

You can open an issue here with an enhancement request - https://github.com/rabbitmq/rabbitmq-server

Please note, however, that the RabbitMQ core team is small and must prioritize other work and work from paying customers. 
 
If your STOMP connection has a unique name you should be able to close just the one connection.  

How would I go about determining that?   I am using a unique username for each connection if that's what you mean.  Or better yet, if you have a handy link to the docs in question, I can dig around there for answers.

AMQP supports a connection name property when a connection is established but it does not appear that this property is available for STOMP connections ... so much for that idea.

Thanks,
Luke


Brad Wood

unread,
Jan 4, 2021, 10:26:15 PM1/4/21
to rabbitm...@googlegroups.com
RabbitMQ never checks auth when delivering a message to a consumer who has subscribed to a queue via basic.consume (which is what a STOMP subscription does under the hood). By that time it is assumed that the client has authenticated successfully and while the consumer is active no further checks are necessary. This applies to all protocols since all piggyback on AMQP and AMQP does not re-auth for message delivery. 

Right, that's basically what I said in the first place :)  The point I'm making is simply
  • when receiving a published message from a STOMP JS client, the backend auth is hit every single time.  It is NOT "assumed that the client has authenticated successfully and while the consumer is active no further checks are necessary"
  • however, when publishing messages to a STOMP JS client, the opposite approach is taken. 
I can't certainly see how a broadcast to a very large number of STOMP clients could have a larger performance impact, which is why I'd suggest some sort of configurable timeout to ensure STOMP clients are re-authenticated every X minutes as a failsafe to weed out stale connections whose permissions have changed.

You can open an issue here with an enhancement request - https://github.com/rabbitmq/rabbitmq-server 


Please note, however, that the RabbitMQ core team is small and must prioritize other work and work from paying customers.  

Yes, of course.  I am also a maintainer of professional open source products myself, and I understand how this works!   In fact, one of my open source projects is the CFML SDK for Rabbit :)  https://www.forgebox.io/view/rabbitsdk

AMQP supports a connection name property when a connection is established but it does not appear that this property is available for STOMP connections ... so much for that idea. 

Actually, I think I can make it work.  Like I said, I'm using a custom username for every STOMP JS client connection.  I can hit the /api/connections endpoint with a GET and iterate over the connections matching them on the "user" property in the JSON.  From there, I can take the "name" property of the connection and then pass a DELETE request to /api/connections/{name}.  It's not particularly pretty, and I don't know if it will scale well, but it does give me something to play with.

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 


--
You received this message because you are subscribed to a topic in the Google Groups "rabbitmq-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/rabbitmq-users/qZx62Kf9k6w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to rabbitmq-user...@googlegroups.com.

Michael Klishin

unread,
Jan 5, 2021, 5:51:22 AM1/5/21
to rabbitmq-users
What is this "STOMP JS" client and what are some specific actionable steps our team can take in order to reproduce? We do not guess in this community,
please help others help you.

Deleting a user will close all of its connections in RabbitMQ versions newer than 3.7.0. If you use unique usernames already, there is no need to revoke any permissions,
simply delete it and the client will be disconnected and won't be able to re-connect.

There is a plugin [1] that caches authZ operation results for a period of time. It can be used to introduce a "permission TTL" without destroying
external HTTP or LDAP services with requests under high message rates.

Michael Klishin

unread,
Jan 5, 2021, 9:55:20 AM1/5/21
to rabbitmq-users
There is a follow-up to this, including my attempts to reproduce using two clients: https://github.com/rabbitmq/discussions/issues/171

Brad Wood

unread,
Jan 5, 2021, 12:13:37 PM1/5/21
to rabbitm...@googlegroups.com
What is this "STOMP JS" client 
 
Hi Michael, "STOMP" stands for "Simple Text Oriented Messaging Protocol" and JS stands for "JavaScript".  A simple Google search will reveal a number of STOMP JS clients out there.  Take your pick, they all do the same thing.  You can learn more about STOMP JS clients in your own docs here: https://www.rabbitmq.com/web-stomp.html 
I'm a little confused why a core Rabbit engineer is asking me what STOMP JS is however.  To be very clear, my question is not about STOMP, how STOMP works, or how to use STOMP.  My question is about RabbitMQ and I only mentioned STOMP to provide some context that the client cannot be trusted with auth decisions as Wesley already made the mistake of suggesting earlier in this thread..  

what are some specific actionable steps our team can take in order to reproduce? 

This is not a bug report, this is a conversation about how (and why) Rabbit behaves in regards to checking permissions when sending a message to a topic subscriber.  If you wanted to see this behavior (which has already been confirmed by your colleague Luke) then I would recommend:
  1. Configure a backend HTTP auth that will log all requests made to its API  
  2. Grab the demo "chat app" from the repo your docs point to ( https://github.com/jmesnil/stomp-websocket/tree/master/example/chat )
  3. Authenticate two users in two different browser windows.
  4. Send a message from one user
  5. Confirm that the backend HTTP auth was consulted whether the user publishing the message had permissions to do so
  6. Also confirm that the user receiving the message did NOT consult the backend HTTP API
If it's unclear, step 6 is the one being discussed here.

We do not guess in this community, 

I'm unclear on what I've asked you to guess.  Luke understood what was being asked.  

please help others help you. 

It would help if you had read the above thread prior to replying :) 

Deleting a user will close all of its connections in RabbitMQ versions newer than 3.7.0. If you use unique usernames already, there is no need to revoke any permissions,
simply delete it and the client will be disconnected and won't be able to re-connect.

There are two issues with this suggestion.
  1. I'm not using internal users, I'm using a custom backend HTTP Auth, as I mentioned in my original post.   The management HTTP API's /api/users/ endpoint only appears to operate on internal users
  2. While I appreciate the workaround, my question is also asking why Rabbit doesn't have a mechanism to re-check the auth itself, especially given the behavior where it re-checks permissions every time it allows a client to publish a message.  
There is a plugin [1] that caches authZ operation results for a period of time 

Yes, I know and I'm using it as per my message I sent to this thread yesterday where I said:
 
" As far as performance, I'm using the cached back end auth to wrap my HTTP backend auth, so the performance implications are minimalized."

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 


Brad Wood

unread,
Jan 13, 2021, 2:33:36 PM1/13/21
to rabbitm...@googlegroups.com
I waited over a week to bump this time.  Michael, you came in hot and heavy and then disappeared.  Do my clarifications make sense and can you provide more information now?

Thanks!

~Brad

Developer Advocate
Ortus Solutions, Corp 

ColdBox Platform: http://www.coldbox.org 


Luke Bakken

unread,
Jan 13, 2021, 4:45:45 PM1/13/21
to rabbitmq-users

Michael Klishin

unread,
Jan 13, 2021, 8:25:25 PM1/13/21
to rabbitmq-users
Hi Brad,

We have responded to your questions on GitHub. I do not feel the need to post everything there and on this list.

Your demanding and belitteling language ("STOMP stands for X, JS stands for Y", thank you!) caught my attention before, and now you are outright attacking
me for asking for details, and assuming that I have not read anything you have posted. It's not entirely uncommon for posts on the Internet to be
misinterpreted. This is why executable ways to reproduce something are so important.

In early January, I have spent several hours comparing the current behavior of STOMP and Web STOMP, and going over where topic authorization is enforced
by channels. Then on GitHub Luke explained one implicit assumptions about consumers and permissions that I have overlooked, and I have moved on to other
things. Now it turns out I am a lazy bum who Mr. Brad from the Internet expects to work harder for him (but not willing to pay or contribute anything, of course).

I am not interested in spending any more time on this discussion. Moreover, as much as I hate doing so (perhaps for the 4th time since 2014, when this list was moved to Google Groups),
I will make sure Mr. Brad won't post anything to this list or GitHub discussions for the next few months.
Open source maintainers have to answer quite a few questions
every single day on various venues, and usually do not even get a Thank you for it. We sure deserve a break from being treated like this.

Michael Klishin

unread,
Jan 13, 2021, 9:04:01 PM1/13/21
to rabbitmq-users
Perhaps we should make it clear to all participants of this list that RabbitMQ core team is not
obligated to respond (the same day or at all) to the threads on this list. This is a community mailing list after all.
Free help and guidance come to the extent our team has the time and focus for. We used to respond to effectively every thread within
a few hours. As the community has grown over time (and so did RabbitMQ scope, deployment scenarios, and so on),
this has become impractical at least for some members of our team.

I specifically no longer participate on this list every single day. Going through every thread takes a substantial amount of time, and while sometimes we do discover real issues or points or improvement,
we often have to invest a non-trivial amount of time to discover that there is nothing actionable for our team, including
topics that have little or nothing to do with RabbitMQ itself. We have no choice but to be selective about what we
investigate and respond to. We always ask for clarifications to save everyone some time. We ask for the same things
(e.g. logs, metrics, an executable way to reproduce the behavior) in every thread, and explaining why we need this information
is getting a bit old.

So some discussions slip through the cracks. That's OK with me: if an issue is common enough it will be reported over and over again.
That's how you know what is worth a closer look.

On one hand, this means that bumps are inevitable. On the other, it does not mean that it's OK to demand responses, ask the same question
in multiple places and then insult the core team for not responding. We get dozens of these every single day, and providing a reasonably
specific and researched responses can take hours or days. The math on how much time answering everything (entirely for free) would take
is not terribly difficult.

Michael Klishin

unread,
Jan 13, 2021, 9:24:39 PM1/13/21
to rabbitmq-users
One specific piece of follow-up perhaps worth reposting here.

A quick attempt at designing an "ongoing" topic authorization re-check for active consumers (which are registered *once* but whose permissions may change) brings up some non-trivial problems.

## Publishers use Specific Topics, Consumers Use Patterns

A topic permission is a pattern. Publishers use specific topics when publishing, and checking a specific topic against a pattern is well defined in the specs and something that several protocol implementations we support already do using tries of segments.

However, *consumers* often consume using patterns as well. Checking a pattern against a pattern is not something well defined and not something we already do. There are real risks to consider this, from meaningful throughput overhead to simply not getting it right as it is not an obvious behavior for implementers and users alike.

So topic authorization that is enforced only on publishers was not a coincidence.

## Consumers are Unaware of Publishers

If we chose to take a specific topic from a message about to be delivered, and use that for topic authorization enforcement,
we would tie consumers to publishers in ways that some protocols we support try to avoid. Now consumers
would have to be aware of certain details of how publishing was done, including certain bits that are not really semantically present in STOMP and are implementation details. It's not obvious to me that this feature would be worth the complication.

## Potentially Non-trivial Changes to Hot Code Path

If we chose to take a specific topic from a message about to be delivered, and use that for topic authorization enforcement,
we would introduce changes to one of the most sensitive code paths there are. It will potentially affect a very large
percentage of the user base, including those who do not use topic permissions.

## No Clear Way to Communicate an Error

In some protocols, there is a way to communicate an error to a client. STOMP is one of them. Unfortunately in MQTT 3.1 this is not possible at all (there is no server-to-client equivalent of an `ERROR` frame). In AMQP 0-9-1, there is a suitable mechanism but most clients do not really expect to be notified of authorization operation failures for running consumers, and using something like consumer cancel notifications can be misinterpreted by both clients and existing applications.

## Conclusion

Addressing this carries very real risks that may be more important than the gain.

M K

unread,
Jan 14, 2021, 2:46:24 PM1/14/21
to rabbitmq-users
After discussing what happened in this thread with more context and fewer emotions,
we lift the posting limitation.

Reply all
Reply to author
Forward
0 new messages