Advanced
Auth Endpoint

The Auth Endpoint

Part of setting up the client-side YSweetProvider is providing it with an endpoint it can use to authorize a user to access a given document. The reason for this design is that it allows the YSweetProvider to fetch a new client token behind the scenes when the old one expires so that the application doesn't have to intervene or ask the user to refresh the page.

The YSweetProvider's authEndpoint value can be configured either as a string or a function that returns a ClientToken. We'll cover both approaches below.

Configuring the authEndpoint with a string

When configuring the YSweetProvider's authEndpoint with a string, you will need to implement the endpoint following a few rules:

  1. The endpoint should handle POST requests
  2. The body of the request will contain the document's ID. E.g., { "docId": "my-doc-id-123" }
  3. The endpoint should perform its own check to confirm the user is authorized to access the given document
  4. The endpoint should call getOrCreateDocAndToken() to create a client token that gives the client access to the document
  5. The endpoint should return the resulting client token as the body of the response.

Here's an example of how an auth endpoint might be implemented using Hono (opens in a new tab):

my-server.ts
import { DocumentManager } from '@y-sweet/sdk'
import { Hono } from 'hono'
import { serve } from '@hono/node-server'
 
const docManager = new DocumentManager(process.env.CONNECTION_STRING)
 
const app = new Hono()
app.post('/api/auth', async (c) => {
  const body = await c.req.json()
  const docId = body.docId
  // At this point, in a production app, you'd want to authenticate the user
  // and make sure they have access to the given doc
  const clientToken = await docManager.getOrCreateDocAndToken(docId)
  return c.json(clientToken)
})
serve(app)

The YSweetProvider can then be configured with a string referencing the endpoint's URL:

my-app.ts
import { createYjsProvider } from '@y-sweet/client'
 
const doc = new Y.Doc()
const docId = 'my-doc-id'
await createYjsProvider(doc, docId, '/api/auth')

Or, if you are using @y-sweet/react, you can configure the <YDocProvider> component:

my-app.tsx
import { YDocProvider } from '@y-sweet/react'
 
const docId = 'my-doc-id'
 
<YDocProvider docId={docId} authEndpoint="/api/auth">
  <MyCollaborativeApp />
</YDocProvider>

Configuring the authEndpoint with a function

When configuring the YSweetProvider's authEndpoint with a function, you still need to hit an endpoint you've implemented on the server that performs an auth check and creates a client token using the @y-sweet/sdk library's getOrCreateDocAndToken(). But you have more flexibility in how you do the auth check. This approach is useful if you need to make the fetch request yourself (to add custom auth headers, or provide the doc ID in a different way, etc). Here's an example of using a function as the authEndpoint value:

my-app.ts
import { createYjsProvider } from '@y-sweet/client'
 
const doc = new Y.Doc()
const docId = 'my-doc-id'
await createYjsProvider(doc, docId, async () => {
  const response = await fetch(`/api/auth?docId=${docId}`, {
    headers: { Authorization: `Bearer ${myCustomAuth}` }
  })
  return await response.json()
})
y-sweet was created by Jamsocket.