Required Real-Time Collaboration configuration options

TinyMCE’s Real-time Collaboration (RTC) plugin will be retired and deactivated on December 31, 2023, and is no longer available for purchase.

The following options are required to use the Real-Time Collaboration (RTC) plugin:

For an example showing the minimum required configuration for RTC, see: Getting started with RTC - Configure the required TinyMCE RTC options.

rtc_document_id

The RTC plugin requires a unique identifier for editor content to enable collaboration, known as the document ID. The identifier set by the integrator is used by the RTC server as a permanent reference for the content. Tiny recommends using the same unique ID used by your server where possible, such as the unique page or document ID from a Content Management System (CMS).

Do not reuse the document ID for different documents, otherwise content will be overwritten. Each document must have a unique identifier.

When a client (user) connects:

  • If the document ID already exists, the most recent version of the content is sent to the client’s editor.

  • If the document ID does not exist, the client uploads the initial content as the first version of that document.

If the content is changed outside of an RTC session, a new document ID must be generated. Changes made outside the RTC session will be overwritten by the content on the RTC server during the next collaboration session.

Type: String

Example: using rtc_document_id

This example shows the minimum required configuration for the Real-Time Collaboration plugin, including the rtc_document_id option.

tinymce.init({
  selector: 'textarea#static-rtc-example',
  plugins: 'rtc',
  rtc_document_id: 'unique-document-id',
  rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
  rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' })
});

rtc_encryption_provider

The RTC plugin requires an encryption key for end-to-end encryption. This key is not sent to the RTC server; the TinyMCE RTC service cannot read the editor content. The encryption key is used by the SubtleCrypto browser API to encrypt and decrypt the editor content in the user’s browser.

A key is required when the client needs to:

  1. Encrypt new data in the collaboration session.

  2. Read previously written data from the collaboration session.

For information on encryption for RTC, including suggestions on how to generate a secure encryption key and use key rotation, see: Real-Time Collaboration (RTC) Encryption Setup.

Type: Function (Returns a Promise)

Input parameters:

Field Type Description

documentId

string

The document ID from the rtc_document_id option.

keyHint

string or null

Key hint returned by the editor when connecting to an existing session. The keyHint is retrieved from the RTC server using the documentId for existing documents.

Return data:

Field Type Required? Description

key

string

required

The encryption key that is used to locally encrypt and decrypt content for the current session. This key needs to be the same for all users connecting to a document (documentId).

keyHint

string

optional

The key hint to provide to future users to assist with retrieving the correct key for a document. It is only recorded when the input keyHint is null.The keyHint must be a unicode string with a max length of 256 characters.

Do not include secret or sensitive information in the key hint. The key hint is stored by the server in plain text.

Example: using rtc_encryption_provider

This example shows the minimum required configuration for the Real-Time Collaboration plugin, including the rtc_encryption_provider option.

tinymce.init({
  selector: 'textarea#rtc-example',
  plugins: 'rtc',
  rtc_document_id: 'unique-document-id',
  rtc_encryption_provider: ({ documentId, keyHint }) =>
    fetch('/getKey', {
      method: 'POST',
      credentials: 'include',
      body: JSON.stringify({ documentId, keyId: keyHint })
    })
      .then((response) => response.json())
      .then(({ keyId, secret }) => ({ key: secret, keyHint: keyId }))
      .catch((error) => console.log('Failed to return encryption key\n' + error)),
  rtc_token_provider: () => Promise.resolve({ token: 'signed-JWT-token' })
});

rtc_token_provider

The RTC plugin and the RTC service uses JSON Web Tokens (JWT) to authenticate the user. The user’s token should include:

  • A unique user ID (sub).

  • A relative expiration time (exp).

The rtc_token_provider function will be called one or more times to refresh the token before it expires. For production usage, Tiny recommends a token provider with a dynamic request that produces a new JWT token with an updated exp claim.

For information on generating and serving JWTs for TinyMCE RTC, see: Real-Time Collaboration (RTC) JWT Authentication Setup.

Type: Function (Returns a Promise)

Input parameters:

Field Type Description

documentId

string

The document ID from the rtc_document_id option.

Return data:

Field Type Description

token

string

A generated JWT token. This token should be signed with a private key as described in JWT authentication.

Required JWT claims

Field Type Description

sub

string

The unique user ID (If sub is the same for two clients, the server will trust them as if they are the same user).

exp

integer

A timestamp indicating the token expiry date and time.

Optional JWT claims

Field Type Description

https://claims.tiny.cloud/rtc/document

string

The document ID that this JWT can access. If omitted, the JWT will be able to access any document on the same account.

https://claims.tiny.cloud/rtc/role

string

The possible role values are: editor or viewer. viewer will put the editor into readonly mode and editor (default) will let the user edit the document.

Example: using rtc_token_provider

This example shows the minimum required configuration for the Real-Time Collaboration plugin, including the rtc_token_provider option.

tinymce.init({
  selector: 'textarea#rtc-example',
  plugins: 'rtc',
  rtc_document_id: 'unique-document-id',
  rtc_encryption_provider: () => Promise.resolve({ key: 'a secret key' }),
  rtc_token_provider: ({ documentId }) =>
    fetch('/getJwtToken', {
      method: 'POST',
      credentials: 'include',
      body: JSON.stringify({ documentId }),
    })
    .then((response) => response.json())
    .then(({ jwt })) => ({ token: jwt })
    .catch((error) => console.log('Failed to return a JWT\n' + error))
});