Skip to main content
One idea at a time

A room name does not grant access

Taskboard lets a live connection subscribe to one project inside a workspace. Socket.IO calls a group a room. A room is a delivery mechanism, not an authorization system.

If the client can freely join project:other-company:project-id, tenant isolation fails even when every HTTP query is correct. The server must decide which rooms a connection may join.

Authenticate the connectionโ€‹

The server validates the browser's session and a CSRF token in the connection auth payload. It also checks the requesting origin because browsers can establish connections from another site. Authentication identifies the user; membership authorizes workspace access. A subscribe message supplies workspace and project UUIDs. The server verifies both before replacing the connection's previous project subscription.

Illustrative connection decision
Session identifies Maya.
Maya is a member of workspace A.
The server permits workspace A notifications.
The server rejects workspace B notifications.

A workspace identifier in a client event is a request, not proof of membership. The server queries current membership or uses another trusted server-side authorization mechanism before placing the connection into a room.

Permissions change after connectionโ€‹

An admin removes Maya while Maya's tab stays open. A connection authenticated an hour earlier must not preserve access indefinitely. The server needs a revocation strategy for existing sockets.

Taskboard's delivery code rechecks the session expiry and workspace membership before emitting to each matching connection. It also checks connected sessions and memberships every five seconds, disconnecting those that lost access. A missed periodic check therefore does not replace the check at delivery. The project subscription and workspace conditions must both match the notification.

The event payload itself needs tenant scope. A job must not broadcast a task ID globally because a handler assumes the ID is harmless. Even identifiers and titles can reveal another company's work.

Test the negative caseโ€‹

The meaningful check connects two users in separate workspaces, changes a task in one workspace, and confirms that only the authorized connection receives its event. A happy-path test proves delivery; it does not prove isolation.

Read the actual authorization and emission conditions in Read api/src/realtime.ts. Session checks are in Read api/src/auth.ts.

Take away

Rooms route messages. Current session and membership rules determine who may receive them, including after a connection has already opened.

Why is a hard-to-guess room name insufficient?

An identifier can leak or be copied. Authorization must check the user's current relationship to the workspace rather than rely on secrecy of the identifier.