Suggestions

close search

Add Messaging, Voice, and Authentication to your apps with Vonage Communications APIs

Visit the Vonage API Developer Portal

End-to-End Encryption

Important: In OpenTok.js 2.27.0, end-to-end encryption will not work with clients using an earlier version of OpenTok.js. When you upgrade your app to use OpenTok.js 2.27.0+, make sure all clients are using OpenTok.js 2.27.0+ if the app uses end-to-end encryption..

This topic includes details on using end-to-end encryption in the OpenTok.js Vonage Video client SDK:

For an overview of end-to-end encryption, see this topic.

Initializing a session with a secret

End-to-end encrypted sessions are created using server APIs (see Enabling encryption using the REST API). To have a web client join an end-to-end encrypted session, specify an encryption secret when calling the OT.initSession() method:

const session = OT.initSession(
  'api-key',
  'session-id',
  {
    encryptionSecret: 'initialEncryptionSecret'
  }
});

A valid secret is a string between 8 and 256 characters. The secret can later be changed with the Session.setEncryptionSecret() method (see Changing the secret, below).

Checking whether the browser supports end-to-end encryption

Use the OT.hasEndToEndEncryptionSupport() method to check if the client's browser supports end-to-end encryption:

if (OT.hasEndToEndEncryptionSupport()) {
  // Proceed with connecting to the session
}
else {
  // Notify the user that they cannot join the session
}

Currently, end-to-end encryption is only supported in Chrome (desktop and mobile), Opera, and Edge. It is not supported in Firefox or Safari. Also, end-to-end encryption is only supported when using the VP8 codec (the default).

Changing the secret

You can change the secret using the Session.setEncryptionSecret() method after the session has connected:

await session.setEncryptionSecret('newEncryptionSecret');

Events and errors

Events and errors are essential to managing the behavior of user-driven encryption behavior. End-to-end encryption uses the shared secret model: everyone in the session is expected to use the same secret to encrypt their media and decrypt everyone else's.

A Subscriber object dispatches an encryptionSecretMismatch event when the subscriber is unable to decode a stream's media. It is important to communicate to the user that media is not being received due to an encryption mismatch and not due to a connection failure or audio/video bug:

subscriber.on('encryptionSecretMismatch', () => {
  // Activate a UI element communicating that there's been an encryption secret mismatch.
});

Also, it is important to communicate to users that encryption has been successfully enabled. A Subscriber object dispatches an encryptionSecretMatch event when the subscriber is able to decode the stream's media after a previous mismatch.

subscriber.on('encryptionSecretMatch', () => {
  // Activate a UI element communicating that the media is being properly decrypted.
});

The Session.connect() callback is invoked with an error if the client tries to connect to an end-to-end encrypted session that was initialized with an invalid encryption secret. A valid secret is a string between 8 and 256 characters. For the best user experience, the application should catch an invalid user supplied secret before calling theOT.initSession() method. In the following example, a session is initialized with an empty (and thus invalid) secret, which causes an error when attempting to connect:

const session = OT.initSession(
 'api-key',
 'e2ee-session-id',
 {
   encryptionSecret: '',
 }
)

session.connect('token', (error) => {
  if (error && error.name === 'OT_INVALID_ENCRYPTION_SECRET') {
    /*
    The application should communicate that the secret was invalid.
    */
  }
});

The Session.connect() callback is invoked with an error if a user attempts to connect to an end-to-end encrypted session in a browser that does not support end-to-end encryption.

const session = OT.initSession(
 'api-key',
 'e2ee-session-id',
 {
   encryptionSecret: 'validEncryptionSecret',
 }
)

session.connect('token', (error) => {
  if (error && error.name === 'OT_UNSUPPORTED_BROWSER') {
    /*
    The error will have the message 'Tried to connect an e2ee session but the browser does not support e2ee'
    The application should communicate that the browser does not support encryption.
    */
  }
});

If a user tries to publish in an end-to-end encrypted session without having specified an encryption secret, the Session.publish() callback is invoked with an error. For the best user experience, the application should validate a user-supplied secret before calling the session.publish() method:

session.publish(publisher, (error) => {
  if (error && error.name === 'OT_STREAM_CREATE_FAILED') {
    /*
    The error will have the message 'Tried to publish to an e2ee session but encryption secret was not set'
    The application should communicate that the secret was not set.
    */
  }
});

If a user tries to subscribe in an end-to-end encrypted session without having specified an encryption secret, the Session.subscribe() callback is invoked with an error. For the best user experience, the application should validate a user-supplied secret before calling the Session.subscribe() method:

subscriber = session.subscribe(stream, target, opts, (error) => {
  if (error && error.name === 'OT_UNABLE_TO_SUBSCRIBE') {
    /*
    The error will have the message 'Tried to subscribe to an e2ee stream but encryption secret was not set'
    The application should communicate that the secret was not set.
    */
  }
});