br41nslug / directus-websocket-subscribe

An extension to subscribe to directus updates over a websocket.
MIT License
106 stars 13 forks source link

Add authorization #1

Closed rijkvanzanten closed 2 years ago

rijkvanzanten commented 2 years ago

A connected websocket client is stateful right? Maybe we could add an "authorize" type that will set the access token of the current session. That way, we could rely on the access token of the session to check against the permissions w/ the regular permissions/authorization middleware before responding over the socket with the requested data 🤔

rijkvanzanten commented 2 years ago

cc @nitwel

br41nslug commented 2 years ago

Interesting idea, for the moment I was more thinking towards doing the authentication at the point where the request gets upgraded then persisting that for the duration of the open socket. That way opening the socket can take advantage of the regular api endpoint api token logic then using the resulting accountability object to access all services to take advantage of the build in authorization there.

br41nslug commented 2 years ago

Altough i do just realize that that wont work for the events pushed by "actions" unless i explicitly fetch the object also 🤔

br41nslug commented 2 years ago

@rijkvanzanten I implemented authentication! In a bit of a limited form but for static user tokens it works 😄

rijkvanzanten commented 2 years ago

Altough i do just realize that that wont work for the events pushed by "actions" unless i explicitly fetch the object also 🤔

Curious to learn more! Are you currently "just" sending through the exact payload from the hook, or are you fetching the modified item fresh, and treating it as a read operation? I believe that's what GraphQL does in its Subscriptions too 🤔

br41nslug commented 2 years ago

I was considering doing an extra fetch on the update action to always return the full object but for now im just passing on the hook payload as-is. I decided to indeed treat all subscribe requests as read operations (doing a single read with accountability before registering the actual message hooks). Optimally i would love to check the permissions before sending any object over the wire but this seemed most practical to start with.

rijkvanzanten commented 2 years ago

Yeah! I was thinking you could treat the hooks as a trigger to execute the read request the user asked for in the initial subscription. That way, we should be able to rely on all the regular permissions and services magic that already exists.

That does make me wonder though: Would you subscribe to single items, or could you also subscribe to a collection? Like every time an item is deleted, give me the most recent 50 items?

br41nslug commented 2 years ago

I think having the option of subscribing to any mutations on a collection is quite valuable already (at least for my usecase) but definitely considering extending that with way to subscribe to a single primary key and/or multiple keys too. And eventually subscribing to a query would be awesome but that would definitely require some thinking on how to implement, im not a big fan of blindly sending the query results on each action fired as none of the items contained might have changed.

rijkvanzanten commented 2 years ago

but definitely considering extending that with way to subscribe to a single primary key and/or multiple keys too

Alternatively, you could provide a "filter" object when you subscribe. That way, you could say: "Send me an update when articles changes, but only when published = true". This in turn also allows subscribing to individual items, as you could say "Let me know when article with ID = 5 is deleted"

im not a big fan of blindly sending the query results on each action fired as none of the items contained might have changed.

Very good point. And you could always just make a "regular" request to refresh that data set if your app needs it.

br41nslug commented 2 years ago

I found a novel way of running the websocket upgrade request through the express app! This way i can directly take advantage of the directus built-in middlewares instead of trying to copy-paste the logic form the directus core :)

rijkvanzanten commented 2 years ago

That's awesome!!