Dynamically unsubscribe a user / revoke subscribe permissions?

86 views
Skip to first unread message

Geordie Millar

unread,
Dec 17, 2014, 11:09:08 PM12/17/14
to autob...@googlegroups.com
Hello

I am writing a GPS location sharing app and I am using Crossbar on the server side and Autobahn on the client side to deliver position updates via WAMP messages.

When the user moves, their location is shared by a WAMP message being published.

I've written custom authentication and authorization services that authenticate the websocket connections per-user, and an authorization service that determines if said user is on the tracked user's friends list before allowing the subscription request. 

The major issue I have here is that if the user being tracked removes the other user from their friends list, the existing subscription stays where it is, and the subscribed user continues to receive position updates.

So, there's a few ways this could be fixed. I'm not averse to implementing this functionality in Crossbar itself if I need to, especially if someone tells me where I should look.

Key questions:

1) Is there a way to remove an existing subscription programatically?

2) Is there a way to clear the authorization cache so all existing authorizations are re-checked - providing they would be?

3) If this doesn't occur, is there a way to drop all the connections for a certain user so that user reconnects and re-subscribes to all the subscriptions?

I'm sure this is a problem for a number of use cases other than my own, so I'd be interested to know how others have solved it.

I haven't found any answers in the docs, haven't seen anything promising reading the source code, and searching this list for anything containing "unsubscribe" turns up nearly every message thanks to the footer...

Thanks in advance. 

Alexander Gödde

unread,
Dec 18, 2014, 8:28:01 AM12/18/14
to autob...@googlegroups.com
Hi Geordie!


The major issue I have here is that if the user being tracked removes the other user from their friends list, the existing subscription stays where it is, and the subscribed user continues to receive position updates.

Valid use case, though not something we've though about explicitly.
 
Key questions:

1) Is there a way to remove an existing subscription programatically?

AFAIK there isn't. Only a subscriber can take actions affecting the existence of the subscription.
 
2) Is there a way to clear the authorization cache so all existing authorizations are re-checked - providing they would be?

I have no idea - this is something for Tobias to answer. 

3) If this doesn't occur, is there a way to drop all the connections for a certain user so that user reconnects and re-subscribes to all the subscriptions?

AFAIK there isn't. Similarly to the subscriptions, only the client itself can take action here. 

I'm sure this is a problem for a number of use cases other than my own, so I'd be interested to know how others have solved it.

I haven't found any answers in the docs, haven't seen anything promising reading the source code, and searching this list for anything containing "unsubscribe" turns up nearly every message thanks to the footer...

 A couple of suggestions of the top of my head (though I realize these are probably not what you are looking for):

1. If the client is trusted, then why not have the client itself unsubscribe? The removal from the friends list triggers a Publish to all clients currently connected for the user and tells them to unsubscribe.

2. You can exclude a client from receiving a subscription, e.g. "session.publish('com.locationapp.user1223.currentlocation", [], {}, {exclude: [sessionID1, sessionID2]}". If the events are published from a backend which knows of current sessions which are no longer authorized, then these could be handled that way.

Regards,

Alex

Geordie Millar

unread,
Jan 6, 2015, 5:06:40 AM1/6/15
to autob...@googlegroups.com
Hello

To avoid a repeat of a certain XKCD, I'm going to outline how I think I've fixed the problem.

1. The client (HTML5 webapp) initiates a websocket connection with the Crossbar server.
2. The client receives a challenge from the server.
3. The client makes a request from the web server side of the app for an authentication token (it's logged into the webapp with a cookie-based session).
4. The client uses this to authenticate the websocket, and the user ID of the client's account is used as the AuthID.
5. The server side then verifies the token and checks that the AuthID the client sends is the same as the one the token was generated for. If the client sends the wrong AuthID the token will be rejected.
6. Another component is registered on wamp.metaevent.session.on_join and wamp.metaevent.session.on_leave and keeps in a separate database a mapping of session IDs to user IDs.

So if this is all successful, we now have the client connection authenticated for that particular user, and a record of it's session ID in a database.
(the database is cleared on application startup in case the app doesn't shut down gracefully, and the record is deleted when the client disconnects)

Then, when an "update" event is pushed from the client, a SQL query is executed to JOIN the table of sessions with the table of which users are authorised to see that user's events. This then produces a list of session IDs which is sent in the "eligible" parameter for the WAMP message, hence if a user is removed, they will immediately not receive any more messages. 

It's not the way I'd like to do it - I'd love to have a way of telling Crossbar to re-evaluate it's permissions and remove subscriptions that authorisation now fails for - but it seems to be working, and looks like the only practical way to do it now.

Thanks.


--
You received this message because you are subscribed to the Google Groups "Autobahn" group.
To unsubscribe from this group and stop receiving emails from it, send an email to autobahnws+...@googlegroups.com.
To post to this group, send email to autob...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/autobahnws/466e31a7-d961-4e92-b6f5-4f3db3b956ff%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tobias Oberstein

unread,
Jan 7, 2015, 5:13:12 AM1/7/15
to autob...@googlegroups.com
Hi Geordie,

sorry, I missed that thread. We first need to establish what you want.

1)
A session that subscribed to a topic can dynamically unsubscribe itself
later on (while the session is still ongoing).

I guess that's clear to you already, but not what you want, right?

2)
Say a session S1 authenticated under role R1 was authorized to subscribe
and did actually subscribe to topic T1.

Now say the authorization to subscribe to topic T1 is removed from role R1.

_New_ sessions authenticating as R1 cannot any longer subscribe to T1.

Further, when S1 unsubscribes (itself), and then again tries to
subscribe to T1, that will fail.

However, when the _existing_ session S1 has an _established_
subscription to T1, and _that_ subscription is _not_ kicked by the router.

Is that the issue we are talking about?

3)
Say a session S1 authenticated under role R1 was authorized to subscribe
and did actually subscribe to topic T1.

A conceivable feature would be for _another_ session S2 (say some kind
of backend management session) being able to actively kick the
subscription of S1 to T1 (independent of retaining or revoking the
_authorization_ of R1 to subscribe T1).

Is that the feature you want?

Cheers,
/Tobias
>> <mailto:autobahnws+...@googlegroups.com>.
>> To post to this group, send email to autob...@googlegroups.com
>> <mailto:autob...@googlegroups.com>.
>> <https://groups.google.com/d/msgid/autobahnws/466e31a7-d961-4e92-b6f5-4f3db3b956ff%40googlegroups.com?utm_medium=email&utm_source=footer>.
>> For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Autobahn" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to autobahnws+...@googlegroups.com
> <mailto:autobahnws+...@googlegroups.com>.
> To post to this group, send email to autob...@googlegroups.com
> <mailto:autob...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/autobahnws/A6344EAB-E1EF-4CCD-BD83-9EFF8B2E8F1C%40stackunderflow.com
> <https://groups.google.com/d/msgid/autobahnws/A6344EAB-E1EF-4CCD-BD83-9EFF8B2E8F1C%40stackunderflow.com?utm_medium=email&utm_source=footer>.

Geordie Millar

unread,
Jan 7, 2015, 5:21:48 AM1/7/15
to autob...@googlegroups.com
On 7 Jan 2015, at 8:43 pm, Tobias Oberstein <tobias.o...@gmail.com> wrote:

Hi Geordie,

sorry, I missed that thread. We first need to establish what you want.

1)
A session that subscribed to a topic can dynamically unsubscribe itself later on (while the session is still ongoing).

I guess that's clear to you already, but not what you want, right?


Yes, that's clear, but I want the subscription revoked from the user side because user A has deleted user B, and user B's client need not be trusted.

2)
Say a session S1 authenticated under role R1 was authorized to subscribe and did actually subscribe to topic T1.

Now say the authorization to subscribe to topic T1 is removed from role R1.

_New_ sessions authenticating as R1 cannot any longer subscribe to T1.

Further, when S1 unsubscribes (itself), and then again tries to subscribe to T1, that will fail.

However, when the _existing_ session S1 has an _established_ subscription to T1, and _that_ subscription is _not_ kicked by the router.

Is that the issue we are talking about?

Yes, this is exactly the issue that I want. I would like a way for S1 to be automatically dropped from it's subscription to T1 as soon as S1 is no longer allowed to subscribe to T1.


3)
Say a session S1 authenticated under role R1 was authorized to subscribe and did actually subscribe to topic T1.

A conceivable feature would be for _another_ session S2 (say some kind of backend management session) being able to actively kick the subscription of S1 to T1 (independent of retaining or revoking the _authorization_ of R1 to subscribe T1).

Is that the feature you want?

Cheers,
/Tobias


Thanks
Geordie Millar


To unsubscribe from this group and stop receiving emails from it, send an email to autobahnws+...@googlegroups.com.
To post to this group, send email to autob...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/autobahnws/54AD06B1.2090205%40gmail.com.

Tobias Oberstein

unread,
Jan 7, 2015, 8:06:21 AM1/7/15
to autob...@googlegroups.com
>> 2)
>> Say a session S1 authenticated under role R1 was authorized to
>> subscribe and did actually subscribe to topic T1.
>>
>> Now say the authorization to subscribe to topic T1 is removed from
>> role R1.
>>
>> _New_ sessions authenticating as R1 cannot any longer subscribe to T1.
>>
>> Further, when S1 unsubscribes (itself), and then again tries to
>> subscribe to T1, that will fail.
>>
>> However, when the _existing_ session S1 has an _established_
>> subscription to T1, and _that_ subscription is _not_ kicked by the router.
>>
>> Is that the issue we are talking about?
>
> Yes, this is exactly the issue that I want. I would like a way for S1 to
> be automatically dropped from it's subscription to T1 as soon as S1 is
> no longer allowed to subscribe to T1.

Ok.

First, this would be a feature of a specific WAMP router - not WAMP as a
protocol per-se (but see below).

Then, this feature isn't implemented in Crossbar.io as of today.

There are noteworthy aspects:

1)
Crossbar.io when using a static node configuration (read from
.crossbar/config.json) sets up role permissions, and due to the fact
that the node config is only read at startup, it cannot change anyway.

Changing the permissions of a role in Crossbar.io dynamically is
(partially) already possible today - but not officially supported yet
(the "management API").

2) If you implement a custom WAMP authorizer for use with Crossbar.io
(ping me if it's unclear what I mean), the authorizer is only called for
the initial authorization request ("is this session allowed to subscribe
T1"), might be cached, but in any case (cached or not), changing the
role's permissions afterwards won't kick existing subscriptions (see 1.)

3) When we implement 1./2., there is this issue left: when a session
subscribes, and the session is not authorized, it'll get an error (the
subcsribe fails). This is clear and transparent to the client app.

However, what should happen when the subscription is later revoked? The
client won't notice! This is somehow not satisfying (lack of transparency).

How should we notice a subscribed session that it's subscription has
been revoked?


Cheers,
/Tobias


Reply all
Reply to author
Forward
0 new messages