---
title: "Authentication with Collaboration"
description: "Generate and manage Collaboration tokens server-side with the unified Tiptap authentication model."
canonical_url: "https://tiptap-docs.lin52025i.qzz.io/guides/authentication"
---

# Authentication with Collaboration

Generate and manage Collaboration tokens server-side with the unified Tiptap authentication model.

Your application signs its own tokens on the server with your environment's private key, which never leaves your server.

This is a quick setup. For the full reference, see [Authentication](https://tiptap-docs.lin52025i.qzz.io/authentication.md) and [Authenticate and authorize in Collaboration](https://tiptap-docs.lin52025i.qzz.io/collaboration/getting-started/authenticate.md).

## Sign a token

Sign tokens on your server with your environment's private key, which must never leave your server. Collaboration tokens set `aud: "Documents"` and carry `permissions` that say which documents the user can reach.

```typescript
import { SignJWT, importPKCS8 } from 'jose'

const privateKey = await importPKCS8(process.env.TIPTAP_PRIVATE_KEY, 'ES256')

const jwt = await new SignJWT({
  permissions: [{ action: 'Documents:Write', resource: '*' }],
})
  .setProtectedHeader({ alg: 'ES256' })
  .setIssuer(process.env.TIPTAP_ENVIRONMENT_ID)
  .setSubject('user-identifier')
  .setAudience(['Documents'])
  .setExpirationTime('30m')
  .sign(privateKey)
// Send this token in the `token` field of the provider. Never expose your private key to a frontend.
```

See [Signing the token](https://tiptap-docs.lin52025i.qzz.io/authentication.md#signing-the-token) for examples in other languages, and [Handle token expiry](https://tiptap-docs.lin52025i.qzz.io/collaboration/getting-started/authenticate.md#handle-token-expiry) for short-lived tokens and revocation.

## Limit access to specific documents

To scope a token to specific documents, set the permission's `resource` to a document name, or use a `prefix` constraint to match a group:

```typescript
const jwt = await new SignJWT({
  permissions: [
    {
      action: 'Documents:Write',
      resource: '*',
      constraints: { prefix: '1500c624-8f9f-496a-b196-5e5dd8ec3c25/' },
    },
  ],
})
  .setProtectedHeader({ alg: 'ES256' })
  .setIssuer(process.env.TIPTAP_ENVIRONMENT_ID)
  .setAudience(['Documents'])
  .setExpirationTime('30m')
  .sign(privateKey)
```

This grants access to every document under that user's prefix. For the previous `allowedDocumentNames` model, see [Legacy authentication](https://tiptap-docs.lin52025i.qzz.io/authentication/legacy.md).
