inrupt / websockets-pubsub

WebSockets pubsub for Solid servers
https://github.com/solid/solid-spec/blob/master/api-websockets.md
MIT License
3 stars 0 forks source link

Implementation questions #2

Open acoburn opened 5 years ago

acoburn commented 5 years ago

Realizing that websockets haven't actually been implemented here (yet!), I would be very interested in hearing how you plan to design this feature. I have implemented this for Trellis according to the SOLID specification, but I haven't yet merged the implementation into master. Eventually, I'd like to get clarification in the specification itself, but having some implementation experience can be really useful when writing up an issue for the spec. I would be interested if any one has insights about any of these questions:

  1. The WebSocket protocol itself does not support authentication (BasicAuth is, effectively, deprecated), and the SOLID spec is silent about both AuthN and AuthZ for WebSockets. One thought I had involved having a client send an auth <token> request before the sub <URL> request, applying the same WebACL rules that exist for resource access.

  2. There are no defined server responses to client requests. For instance, if the auth method is supported, should the server indicate whether that request succeeded? What if a client tries to subscribe to a resource URL that doesn't exist or which is not in the domain of the server? If auth is supported, what if a client subscribes to a resource that the client can't access? What if the client sends a syntactically invalid payload?

  3. Can a client send multiple sub <URL> requests? That is, can a single WebSocket connection be used to listen to multiple resources? Or would a second request effectively end the first request?

  4. Should the payloads be more structured than just <command> <URL>? I like the simplicity of the current structure, but if JSON-LD was used, it might make it easier to extend the existing behaviors (it may also make the protocol more difficult to consume and implement).

  5. If a client subscribes to a container (e.g. /container), should that client be notified of changes only to direct descendants (e.g. /container/child) or all descendants, transitively (e.g. /container/subcontainer/subsubcontainer/child)

michielbdejong commented 5 years ago

Thanks! Will try out your implementation too.

I think 1) authorization header in the http upgrade request through which the WebSocket gets established, 2) no responses, the client flies blind, 3) yes, multiple, 4) I kind of like the simplicity, 5) I think all descendants.

We can consider https://GitHub.com/solid/node-solid-ws as a reference implementation except for Auth (see open issues on that repo)..

michielbdejong commented 5 years ago

Note that there is no way to unsubscribe other than closing the WebSocket

acoburn commented 5 years ago

For items 2-5, that seems just fine (as does the issue about unsubscribing by closing the WebSocket). I'm a bit unclear on the first issue, though. The JavaScript API for establishing a WebSocket:

WebSocket(url[, protocols])

does not provide a facility for sending additional headers during the connection upgrade stage, so I'm not sure how the Authorization header could be used, except by sending the value as a payload through an already-opened connection (e.g. auth <token>).

michielbdejong commented 5 years ago

Right, bummer, that's a problem. So then auth <token> seems the cleanest option there, but that's definitely a breaking spec change. Another option that would not be breaking would be to include either an access ticket (as per https://devcenter.heroku.com/articles/websocket-security#authentication-authorization, requires a server-side tickets database) or the entire token in the Updates-Via URL. @jaxoncreed what do you think? Let's also discuss with @dmitrizagidulin next week.

acoburn commented 5 years ago

The access ticket technique is not so different from the auth <token> approach. In both cases, a client first opens a WebSocket and then sends along a data payload as a way to authenticate itself.

Also, if not sending an auth <token> (i.e. as per the current spec) is understood as a session with an unauthenticated user, then sending an auth command may not necessarily be a breaking change to the spec; a change, certainly, but more along the lines of an extension.

michielbdejong commented 5 years ago

I understood the access ticket technique as the first request being just http to obtain the ticket (so there an in-browser client can provide a bearer token), then the second one being a websocket request with the auth ticket token in the URL.

i see your point that it's not a breaking change to add the auth mechanism, if we start from the view that the current spec does not support auth. But I'm trying to invent a way to fix the lack of auth in the current node-solid-ws implementation, without breaking the Solid apps that currently use WebSockets (that means mainly the databrowser and the recent chat apps, i think). So that would mean the server should either set a cookie and look for that, or include some secret in the Updates-Via header.

acoburn commented 5 years ago

That's a good point about placing the access token in the WebSocket URL (e.g. with a query parameter): that would definitely be one approach. I'd be a little concerned about replay attacks, since the token's value would typically be logged by any webserver or proxy, but as long as the specification is clear about the security implications, that would be fine. Using a Cookie would be another viable approach.

Perhaps we just need more implementation experience here to inform the specification.

RubenVerborgh commented 5 years ago

Suggest to split these questions in specific issues. See https://github.com/inrupt/websockets-pubsub/issues/5 for instance

csarven commented 4 years ago

Note that there is no way to unsubscribe other than closing the WebSocket

True. There is a consideration for an unsub command here: https://github.com/solid/specification/issues/167