@localfirst/auth-syncserver
TypeScript icon, indicating that this package has built-in type declarations

6.0.0 • Public • Published

@localfirst/auth logo

Authenticated sync server for Automerge Repo

This is a sync server that uses @localfirst/auth-provider-automerge-repo to authenticate connections with peers.

This sync server works much the same way as the automerge-repo sync server, in that is fundamentally just another peer running automerge-repo.

The sync server needs to be added to every team we want to sync with, and it needs to have a full copy of the team graph. Instead of going through the invitation process, the sync server exposes an REST API to obtain its public keys and to provide it with a team's graph.

Instantiating a sync server

The server's hostname (without the port) is used as its unique identifier. Here we use localhost; in production this would look like sync.my-organization.com.

const host = 'localhost'
const port = 3030
const url = `${host}:${port}`
const storageDir = 'localfirst-auth-syncserver-storage'
const syncServer = new LocalFirstAuthSyncServer(host)
await syncServer.listen({ port, storageDir })

Connecting to the sync server

A user creates an auth provider with a reference to the server's hostname, and instantiates a repo as described here.

// Instantiate a user's auth provider.
const user = Auth.createUser('alice')
const device = Auth.createDevice(user.userId, 'ALICE-MACBOOK-2023')
const storage = new SomeStorageAdapter()
const authProvider = new AuthProvider({
  user,
  device,
  storage,
  server: 'localhost:3030',
})

// Instantiate a repo.
const adapter = new SomeNetworkAdapter()
const network = [authProvider.wrap(adapter)]
const repo = new Repo({ network, storage })

// Create a team.
const team = await authProvider.createTeam(`Alice's team`)

A new team needs to be registered with the sync server using the API described below. The AuthProvider.createTeam() method automatically does this for you. If you create the team outside the auth provider, you can use the AuthProvider.registerTeam() method.

const team = Auth.createTeam('team A', aliceContext)
authProvider.addTeam(team)
await authProvider.registerTeam(team)

On the team, the server is treated more or less like a device with no user. The server can't make any changes to the team's membership etc.; it can only relay changes made by team members. But the server can verify invitations and admit new members and devices to the team.

Any number of servers can be registered with a team, and any number of teams can be registered with a server.

The repo will now connect with the server, the auth provider will authenticate with it, and the repo should get a peer event.

repo.networkSubsystem.on('peer', ({ peerId }) => {
  console.log(peerId) // `localhost` or `sync.my-organization.com`
})

From this point on, our communication with the sync server takes place over an encrypted channel. All subsequent changes to the team (inviting or removing members, etc.) will be automatically synced with the server.

Server API

The sync server exposes two endpoints that are used when adding a new team.

(You wouldn't normally access this API yourself; the AuthProvider.createTeam() and AuthProvider.registerTeam() methods call these endpoints for you.)

GET /keys

Obtains the server's public keys. We need these to add the server to the team.

const response = await fetch(`http://${url}/keys`)
const keys = await response.json()

// Use these keys to add the server to the team
team.addServer({ host, keys })

POST /teams

Registers the team with the sync server by giving it a complete copy of the team's data.

await fetch(`http://${url}/teams`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    serializedGraph: team.save(), // the serialized team is encrypted
    teamKeyring: team.teamKeyring(), // these are needed to decrypt the serialized team
  }),
})

Readme

Keywords

none

Package Sidebar

Install

npm i @localfirst/auth-syncserver

Weekly Downloads

3

Version

6.0.0

License

MIT

Unpacked Size

26.1 kB

Total Files

10

Last publish

Collaborators

  • herbcaudill