Skip to content

Synchronizers support different levels of permissions for different usersΒ #230

@george-blackburn-axomic

Description

Is your feature request related to a problem? Please describe.
I want to be able to restrict which users can access or make changes to a synchronized store. This would mean that stores unique to users are protected, and that stores can be exposed to non-privileged users without allowing them to make changes.

Describe the solution you'd like

// Synchronizer on the client side returns an updateTokenCallback function
// that can be used to set the token for the synchronizer, calling this will
// store the token, close any existing websocket and open a new one. Negotiating
// with the target
const ws = new ReconnectingWebSocket(`ws://server-web-socket/`);
const synchronizer, updateTokenCallback = await createWsSynchronizerWithToken(
  store1,
  new WebSocket('ws://localhost:8047'),
);

// On the server side provide a token validator function to the server
enum Permissions {
  READ = 'READ',
  WRITE = 'WRITE',
  DELETE = 'DELETE',
}
type token_validator = (token: string, context: ??) => Permissions[];
const server = createWsServerWithTokenAuth(
  new WebSocketServer({port: 8048}),
  (token: string, context: ??) => {
    // User defined validator function which returns permissions
  }
);

Tinybase isn't responsible for:

  1. Managing tokens or validating them.
  2. Re-aligning clients that have made changes to their stores that they don't have permissions for.

It's responsible for:

  1. Exchanging the token between the client and the server when the websocket is initially set up.
  2. Preventing websockets being opened where there are no read permissions.
  3. Closing down any websockets where update / delete permissions are violated.

Describe alternatives you've considered
For handling access to the store you can provide a token from the client to the server via the query string, this can then be checked by the WebSocketServer before the websocket is established.

It's also possible to extend the WebSocket / WebSocketServer classes so that they can get access to the message before it's synchronised to the server store so you can run auth checks on every message. (See WebSocketServerWrapper.ts and WebSocketWrapper.ts for some poorly written examples).

However, there's no easy way to tell what a message from the client is attempting to do, nor the permissions it would require. I could parse the message myself, extract the Message enum to check if it's performing a write operation but as the parse function isn't exposed in the library this feels brittle and doesn't allow differentiating between update, create, or delete operations.

Additional context
It would also be useful if a clients store could be marked as read-only except by synchronizers. This give me a lot more confidence that my app won't be able to accidentally make local changes and then never be able to sync with the server again due to lack of permissions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions