https://github.com/raineorshine/y-websocket-auth
Websockets provider for Yjs with access token authentication
https://github.com/raineorshine/y-websocket-auth
Last synced: 2 months ago
JSON representation
Websockets provider for Yjs with access token authentication
- Host: GitHub
- URL: https://github.com/raineorshine/y-websocket-auth
- Owner: raineorshine
- License: mit
- Created: 2022-12-14T16:06:49.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2022-12-27T17:04:54.000Z (over 2 years ago)
- Last Synced: 2025-04-11T03:52:34.758Z (2 months ago)
- Language: JavaScript
- Homepage:
- Size: 748 KB
- Stars: 12
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# y-websocket-auth :tophat: :key:
[](https://www.npmjs.com/package/y-websocket-auth)
**y-website-auth is a fork of [y-websocket](https://github.com/yjs/y-websocket) with access token authentication**
- Authenticates every websocket message using a given access token.
- Closes the websocket connection when unauthorized.
- Does not perform any particular authentication method (usernmae/password, JWT, etc)... that's up to you.
- Implementation is based on https://github.com/yjs/y-websocket/issues/7#issuecomment-623114183 (thanks to [@WinstonFassett](https://github.com/WinstonFassett))## Install
```sh
npm i y-websocket-auth
```## Usage
Create a server (e.g. `server.js`) with your own authenticate function:
```ts
const { createServer } = require('y-websocket-auth/server')const server = createServer({
// accessToken is passed as { auth: ACCESS_TOKEN }
// in the WebsocketProvider constructor on the client-side
authenticate: async (accessToken: string) => {
// do authentication
return true
}
})server.listen(port, host, () => {
console.log(`running at '${host}' on port ${port}`)
})
```client.js:
```ts
import * as Y from 'yjs'
import { WebsocketProvider } from 'y-websocket-auth'const doc = new Y.Doc()
const wsProvider = new WebsocketProvider(
'ws://localhost:1234',
'my-roomname',
doc,
{ auth: ACCESS_TOKEN }
)wsProvider.on('status', event => {
console.log(event.status) // logs "connected" or "disconnected"
})
```If you are running the client in NodeJS instead of the browser, you will need to polyfill the [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) object:
```ts
const wsProvider = new WebsocketProvider(
'ws://localhost:1234',
'my-roomname',
doc,
{ auth: ACCESS_TOKEN, WebSocketPolyfill: require('ws') }
)
```Start the server:
```sh
node server.js
```Default configuration can be changed with env variables:
```sh
# host name
HOST=localhost#port
PORT=1234# directory to persist ydoc
YPERSISTENCE=./.persistence.level
```## Contributing
```
# fork the repo: https://github.com/raineorshine/y-websocket-auth/fork
git clone https://github.com/YOUR_NAME/y-websocket-auth
npm install
npx tsc -w
```---
# y-websocket :tophat:
The Websocket Provider implements a classical client server model. Clients connect to a single endpoint over Websocket. The server distributes awareness information and document updates among clients.
The Websocket Provider is a solid choice if you want a central source that handles authentication and authorization. Websockets also send header information and cookies, so you can use existing authentication mechanisms with this server.
* Supports cross-tab communication. When you open the same document in the same browser, changes on the document are exchanged via cross-tab communication ([Broadcast Channel](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API) and [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) as fallback).
* Supports exchange of awareness information (e.g. cursors)....
## API
```js
import { WebsocketProvider } from 'y-websocket'
```
- Create a new websocket-provider instance. As long as this provider, or the connected ydoc, is not destroyed, the changes will be synced to other clients via the connected server. Optionally, you may specify a configuration object. The following default values of wsOpts can be overwritten.
wsProvider = new WebsocketProvider(serverUrl: string, room: string, ydoc: Y.Doc [, wsOpts: WsOpts])
```js
wsOpts = {
// Set this to `false` if you want to connect manually using wsProvider.connect()
connect: true,
// Specify a query-string that will be url-encoded and attached to the `serverUrl`
// I.e. params = { auth: "bearer" } will be transformed to "?auth=bearer"
params: {}, // Object
// You may polyill the Websocket object (https://developer.mozilla.org/en-US/docs/Web/API/WebSocket).
// E.g. In nodejs, you could specify WebsocketPolyfill = require('ws')
WebsocketPolyfill: Websocket,
// Specify an existing Awareness instance - see https://github.com/yjs/y-protocols
awareness: new awarenessProtocol.Awareness(ydoc),
// Specify the maximum amount to wait between reconnects (we use exponential backoff).
maxBackoffTime: 2500
}
```
- True if this instance is currently connected to the server.
- True if this instance is currently connecting to the server.
- If false, the client will not try to reconnect.
- True if this instance is currently communicating to other browser-windows via BroadcastChannel.
- True if this instance is currently connected and synced with the server.
- Disconnect from the server and don't try to reconnect.
- Establish a websocket connection to the websocket-server. Call this if you recently disconnected or if you set wsOpts.connect = false.
- Destroy this wsProvider instance. Disconnects from the server and removes all event handlers.
- Add an event listener for the sync event that is fired when the client received content from the server.
- Receive updates about the current connection status.
- Fires when the underlying websocket connection is closed. It forwards the websocket event to this event handler.
- Fires when the underlying websocket connection closes with an error. It forwards the websocket event to this event handler.
wsProvider.wsconnected: boolean
wsProvider.wsconnecting: boolean
wsProvider.shouldConnect: boolean
wsProvider.bcconnected: boolean
wsProvider.synced: boolean
wsProvider.disconnect()
wsProvider.connect()
wsProvider.destroy()
wsProvider.on('sync', function(isSynced: boolean))
wsProvider.on('status', function({ status: 'disconnected' | 'connecting' | 'connected' }))
wsProvider.on('connection-close', function(WSClosedEvent))
wsProvider.on('connection-error', function(WSErrorEvent))
## Websocket Server
Start a y-websocket server:
```sh
HOST=localhost PORT=1234 npx y-websocket
```
Since npm symlinks the `y-websocket` executable from your local `./node_modules/.bin` folder, you can simply run npx. The `PORT` environment variable already defaults to 1234, and `HOST` defaults to `localhost`.
### Websocket Server with Persistence
Persist document updates in a LevelDB database.
See [LevelDB Persistence](https://github.com/yjs/y-leveldb) for more info.
```sh
HOST=localhost PORT=1234 YPERSISTENCE=./dbDir node ./node_modules/y-websocket/bin/server.js
```
### Websocket Server with HTTP callback
Send a debounced callback to an HTTP server (`POST`) on document update. Note that this implementation doesn't implement a retry logic in case the `CALLBACK_URL` does not work.
Can take the following ENV variables:
* `CALLBACK_URL` : Callback server URL
* `CALLBACK_DEBOUNCE_WAIT` : Debounce time between callbacks (in ms). Defaults to 2000 ms
* `CALLBACK_DEBOUNCE_MAXWAIT` : Maximum time to wait before callback. Defaults to 10 seconds
* `CALLBACK_TIMEOUT` : Timeout for the HTTP call. Defaults to 5 seconds
* `CALLBACK_OBJECTS` : JSON of shared objects to get data (`'{"SHARED_OBJECT_NAME":"SHARED_OBJECT_TYPE}'`)
```sh
CALLBACK_URL=http://localhost:3000/ CALLBACK_OBJECTS='{"prosemirror":"XmlFragment"}' npm start
```
This sends a debounced callback to `localhost:3000` 2 seconds after receiving an update (default `DEBOUNCE_WAIT`) with the data of an XmlFragment named `"prosemirror"` in the body.
## License
[The MIT License](./LICENSE) © Kevin Jahns