Sign inGet started

Canales cifrados

Un canal cuyo nombre empieza con private-encrypted- tiene cifrado de extremo a extremo. Tu servidor cifra cada payload antes de publicarlo, y los clientes de navegador autorizados lo descifran con una clave de tu endpoint de autorización. El edge de Realtime y los intermediarios de red solo ven texto cifrado.
Genera y almacena una clave maestra de 32 bytes. La clave maestra nunca aparece en una solicitud API de Realtime, y el prefijo del nombre del canal activa la funcionalidad. Bird no puede recuperar una clave perdida, y los payloads cifrados con esa clave permanecen ilegibles después de reemplazarla.
Los canales cifrados usan el mismo endpoint y firma que los canales privados. La respuesta de autorización también incluye la clave de descifrado derivada del canal como shared_secret. Rechazar una suscripción impide que ese cliente reciba la clave.

Generar una clave maestra

Genera 32 bytes aleatorios, codifícalos en base64 y almacena el valor como el secreto de la app:
Ejemplo de código
openssl rand -base64 32
Pásalo a tu SDK de servidor como parte de la configuración de realtime, junto a la clave y el secreto de la app.

Publicar un evento cifrado

El SDK de servidor detecta el prefijo del canal, deriva su clave a partir de la clave maestra y cifra el payload JSON localmente. La solicitud de publicación contiene el sobre cifrado.
import { BirdClient } from "@messagebird/sdk";

const bird = new BirdClient({
  apiKey: process.env.BIRD_API_KEY,
  realtime: {
    key: process.env.BIRD_REALTIME_KEY,
    secret: process.env.BIRD_REALTIME_SECRET,
    encryptionMasterKey: process.env.BIRD_REALTIME_MASTER_KEY,
  },
});

await bird.realtime.publish("rap_01krdgeqcxet5s7t44vh8rt9mg", {
  event: "order.updated",
  channels: ["private-encrypted-orders"],
  data: { order_id: "ord_123", status: "shipped" },
});
Un canal cifrado debe ser el único canal en una sola publicación. Cada canal cifrado deriva una clave diferente, por lo que otros canales no podrían descifrar el mismo payload cifrado. Los SDK rechazan este fan-out localmente, y el API devuelve E23000 si recibe uno. Para publicar en varios canales cifrados, usa un batch con un canal por evento.

Devolver el secreto compartido desde tu endpoint de autorización

Tu endpoint de autorización aprueba las suscripciones cifradas del mismo modo que aprueba las privadas. Usa el helper authorizeChannel del SDK y la respuesta incluye el shared_secret automáticamente siempre que el nombre del canal lleve el prefijo cifrado:
app.post("/bird/auth", async (req, res) => {
  const { connection_id, channel_name } = req.body;

  const user = getUserFromSession(req);
  if (!user || !mayJoin(user, channel_name)) return res.sendStatus(403);

  res.json(
    await bird.realtime.authorizeChannel({
      connectionId: connection_id,
      channelName: channel_name,
    }),
  );
});
El SDK deriva un shared_secret separado para cada canal. La autorización para private-encrypted-orders no descifra private-encrypted-invoices. El secreto viaja en tu respuesta de autorización y no se incluye en el frame de suscripción enviado al edge.

Suscribirse y descifrar en el navegador

El cifrado usa el punto de entrada @messagebird/realtime/encrypted separado. Impórtalo y pásalo como la opción encryption del cliente:
Ejemplo de código
import { BirdRealtime } from "@messagebird/realtime";
import { encryption } from "@messagebird/realtime/encrypted";

const bird = new BirdRealtime({
  appKey: "your-app-key",
  region: "us1",
  authEndpoint: "/bird/auth",
  encryption,
});

const orders = bird.subscribe("private-encrypted-orders");
orders.bind("order.updated", (data) => {
  console.log(data); // decrypted: { order_id: "ord_123", status: "shipped" }
});
Los bindings reciben texto plano. Suscribirse sin la opción encryption lanza un error de inmediato, y una respuesta de autorización sin shared_secret falla la suscripción.
Solo el cliente de navegador recibe actualmente canales cifrados. Los clientes de Swift y Kotlin rechazan las suscripciones private-encrypted- porque no implementan el descifrado.

Rotar la clave maestra

Despliega la nueva clave en todos los publicadores y endpoints de autorización a la vez. Durante la rotación:
  1. Las nuevas publicaciones se cifran con la nueva clave.
  2. Un cliente de navegador suscrito que no pueda descifrar un evento se reautoriza una vez y obtiene el nuevo shared_secret.
  3. Las instancias que usen claves maestras distintas pueden publicar brevemente eventos que algunos clientes no puedan descifrar; coordina el despliegue entre instancias.
Rota una clave filtrada o perdida. La rotación protege los payloads futuros, pero no puede volver a cifrar eventos anteriores ni revocar copias de la clave anterior.

Lo que los canales cifrados no hacen

  • Los clientes oficiales no admiten eventos de cliente. El trigger() de navegador lanza un error en canales cifrados porque el cliente no cifra los payloads de cliente a cliente. No envíes eventos de cliente en texto plano desde un cliente personalizado.
  • Presencia y cifrado no se pueden combinar. El prefijo presence-encrypted- no es compatible. Cache y cifrado sí funcionan juntos: los canales private-encrypted-cache- almacenan el evento en caché cifrado, aunque tras una rotación de clave la copia en caché permanece cifrada con la clave anterior hasta que la siguiente publicación la reemplace.
  • Los nombres de canal y de evento no se cifran. Solo se cifra el payload. Elige nombres de canal que no revelen lo que estás protegiendo.
  • El edge de Realtime no puede inspeccionar los payloads. Los nombres de canal y de evento permanecen visibles, mientras que el payload se mantiene cifrado.

Próximos pasos