-
-
Notifications
You must be signed in to change notification settings - Fork 187
Description
Description
First, I would like to congratulate you on such a great product—you’re building something fantastic.
Now, regarding the issue:
Context:
I want to validate whether the userName present in a document cursor coming from the front-end (we’re using BlockNote) matches the authenticated user in the Hocuspocus server context.
While working on this, I noticed that the onAwarenessUpdate hook (from Hocuspocus) always provides the same context in the data parameter—specifically, the context of the first user who joined the document. Even when a second user joins, the added list (containing the clientId of the recently added user) still appears to be associated with the context of the first user.
To make things even stranger, the awareness state map (retrieved via awareness.getStates()) only contains the clientId (which, as far as I understand, is created whenever a user creates a cursor to join the document) and the user information defined by the client (Therefore we cannot fully trust the second portion of the information).
If that’s the case, the first time I see a clientId is inside the onAwarenessUpdate hook. Because of this, I have no way to associate that clientId with any other server-side information (such as the WebSocket connection, socketId, so on). This becomes a problem if I need to disconnect a newly added clientId due to a userName mismatch (client tells a diffetent name from that of the server - completely feasable).
Steps to reproduce the bug
- Create a basic client that connects to the server and allows choosing a
userName
(in my case, I used BlockNote, which allows setting the user name). - Create a Hocuspocus server with at least the
onAwarenessUpdatehook, and log thesocketIdfrom the connection data. - Open the first client connection.
- Observe the logs showing the
socketIdand the correspondingclientId. - Open a second client connection.
- Observe that the context received in the hook’s
dataparameter is still the same as before (compare thesocketIds), even though there is a newclientIdadded to the awareness state.
Expected behavior
I would expect at least one of the following scenarios to be possible to validate the userName from the cursor (ideally all of them):
-
Expose
clientIdearlier or elsewhere
For example, passing theclientIdto theonAuthenticatehook, so we can associate aclientIdwith asocketId(and, by extension, the WebSocket connection).
This might already exist, but I couldn’t find it. -
Include server-side identifiers in awareness states
For example, storing thesocketId(or another server-defined identifier) alongside the client data inawareness.getStates().
I understand this might be a bit more difficult than the first. -
Bind awareness changes to the originating client context
Meaning that awareness updates (e.g., cursor changes) would be handled using the context of the client that triggered that change.
That way, everyclientIdobserved inonAwarenessUpdatewould be directly associated with the correct user context, and therefore the websocket connection completely.
This is probably the most complex option.
Environment
- Operating system: Ubuntu 22.04
- Browser: Chrome v140.0.7339.80
- Platform: Desktop
- Hocuspocus version: v3.4.4
- BlockNote version: v0.31.1
Additional context
It’s very likely that I’m missing something here—if so, please let me know. Thank you in advance for your help.
There is also an open PR in our repository for integrating BlockNote with BigBlueButton, which might help clarify the broader context of this issue:
bigbluebutton/bigbluebutton#24519
In there we use Hocuspocus in the server component named bbb-shared-notes-server;
I am open to discussion, let me know if you have any questions.
Thanks for your time, and keep up the great work!