Kapitel 2

Pruefsumme & Authentifizierung

Jeder BigBlueButton-API-Aufruf muss eine checksum enthalten, die aus dem shared secret des Servers berechnet wird. Dieser Mechanismus verhindert unbefugten Zugriff und schützt API-Anfragen vor Manipulation.

So funktioniert es

Die BBB-API verwendet ein shared-secret-Modell: Sowohl der Server als auch die aufrufende Anwendung kennen dasselbe Secret. Das Secret wird niemals direkt übertragen — stattdessen wird es als Eingabe für einen kryptografischen hash verwendet, der jeder Anfrage als Parameter checksum angehängt wird.

Das shared secret darf Endbenutzern niemals offengelegt werden. Es gehört ausschließlich in die serverseitige Konfiguration der integrierenden Anwendung. Betten Sie es niemals in JavaScript, mobile Apps oder anderen clientseitigen Code ein.

Abrufen des Shared Secret

Das Geheimnis ist auf dem BigBlueButton-Server in /etc/bigbluebutton/bbb-web.properties als Eigenschaft securitySalt gespeichert. Sie können es abrufen, indem Sie den folgenden Befehl auf dem Server ausführen:

# On the BBB server:
sudo bbb-conf --secret

Beispielausgabe:

URL: https://api-guide.bbbserver.com/bigbluebutton/
Secret: replace-with-secret

Berechnung der Checksum (Schritt für Schritt)

Das folgende Beispiel demonstriert, wie die checksum für einen create-API-Aufruf mit SHA-256 berechnet wird.

— setzen Sie alle Parameter außer checksum zusammen:

name=Demo&meetingID=replace-with-meeting-id&attendeePW=replace-with-password&moderatorPW=replace-with-password

Stellen Sie den API-Methodennamen voran (ohne Trennzeichen):

createname=Demo&meetingID=replace-with-meeting-id&attendeePW=replace-with-password&moderatorPW=replace-with-password

Hängen Sie das shared secret an (ohne Trennzeichen):

createname=Demo&meetingID=replace-with-meeting-id&attendeePW=replace-with-password&moderatorPW=replace-with-passwordreplace-with-secret

Berechnen Sie den hash mit dem gewählten Algorithmus (SHA-256 in diesem Beispiel):

SHA-1:   7030bd96ede6a7ac41da848fe3bfc562e52a5914
SHA-256: 7e5a0a48f1542462e56ca034dc83d741bff1deb5feab0cd9ef74fa6e009fe1fd

Hängen Sie die checksum als Parameter an den Query-Stringchecksum an:

name=Demo&meetingID=replace-with-meeting-id&attendeePW=replace-with-password&moderatorPW=replace-with-password&checksum=7e5a0a48f1542462e56ca034dc83d741bff1deb5feab0cd9ef74fa6e009fe1fd

Unterstützte Hash-Algorithmen

BigBlueButton unterstützt mehrere hash-Algorithmen zur Berechnung der checksum. Die folgende Tabelle listet alle verfügbaren Optionen auf:

Algorithmus Verfügbar seit Hash-Länge
SHA-1 Alle Versionen 40 Zeichen
SHA-256 BBB 2.4 64 Zeichen
SHA-384 BBB 2.5 96 Zeichen
SHA-512 BBB 2.5 128 Zeichen

Die unterstützten Algorithmen werden serverseitig in /etc/bigbluebutton/bbb-web.properties konfiguriert:

supportedChecksumAlgorithms=sha256,sha384,sha512

Wenn ein Algorithmus aus dieser Liste entfernt wird, wird er auf dem Server deaktiviert. Standardmäßig sind alle vier Algorithmen aktiviert.

SHA-1 gilt als veraltet. Verwenden Sie für neue Implementierungen SHA-256 oder höher. Lassen Sie SHA-1 nur aktiviert, wenn Sie Abwärtskompatibilität mit älteren Integrationen benötigen.

POST-Anfragen

Beachten Sie bei POST-Anfragen an die BigBlueButton-API die folgenden Regeln:

  • Die checksum wird ausschließlich aus dem URL-Query-String berechnet.
  • Der POST-Body (z. B. Präsentations-XML oder clientSettingsOverride) wird nicht in die Berechnung der checksum einbezogen.
  • Alle Parameter, die Teil der checksum sein sollen, müssen im Query-String platziert werden.

Konfiguration der Breakout-Räume

Wenn Sie die Unterstützung für SHA-256 deaktivieren, müssen Sie auch die Einstellung checkSumAlgorithmForBreakouts in /etc/bigbluebutton/bbb-apps-akka.conf aktualisieren, damit Gruppenräume weiterhin korrekt funktionieren.

Bewährte Sicherheitspraktiken

  • Speichern Sie das Shared Secret nur serverseitig — niemals in JavaScript, mobilen Apps oder anderen clientseitigen Kontexten.
  • Verwenden Sie immer HTTPS, um die Prüfsumme und Parameter während der Übertragung zu schützen.
  • Wenn Sie vermuten, dass das Secret kompromittiert wurde, rotieren Sie es sofort mit bbb-conf --setsecret <new-secret>.
  • Der Mechanismus der Prüfsumme schützt vor Manipulationen, aber nicht vor Replay-Angriffen. Erwägen Sie für join-URLs die Verwendung des Parameters createTime, um die Gültigkeit zu begrenzen.

Wenn Sie join-Links für Benutzer generieren, fügen Sie den Parameter createTime aus der ursprünglichen create-Antwort ein. Dadurch wird sichergestellt, dass der Join-Link nur für diese bestimmte Meeting-Instanz gültig ist.

Codebeispiele

Die folgenden Beispiele demonstrieren die Berechnung der Prüfsumme mit SHA-256, um ein Meeting zu erstellen.

Python 3

import hashlib
import urllib.parse
import requests

BBB_URL = "https://api-guide.bbbserver.com/bigbluebutton/api"
BBB_SECRET = "replace-with-secret"

def bbb_checksum(call_name: str, query_string: str) -> str:
    """Calculate the BBB API checksum (SHA-256)."""
    raw = call_name + query_string + BBB_SECRET
    return hashlib.sha256(raw.encode("utf-8")).hexdigest()

# Create a meeting
params = urllib.parse.urlencode({
    "name": "Demo",
    "meetingID": "replace-with-meeting-id",
    "attendeePW": "replace-with-password",
    "moderatorPW": "replace-with-password",
})
checksum = bbb_checksum("create", params)
response = requests.get(f"{BBB_URL}/create?{params}&checksum={checksum}")
print(response.text)

PHP

<?php
$bbbUrl    = "https://api-guide.bbbserver.com/bigbluebutton/api";
$bbbSecret = "replace-with-secret";

function bbbChecksum(string $callName, string $queryString, string $secret): string {
    return hash("sha256", $callName . $queryString . $secret);
}

// Create a meeting
$params = http_build_query([
    "name"        => "Demo",
    "meetingID"   => "replace-with-meeting-id",
    "attendeePW"  => "replace-with-password",
    "moderatorPW" => "replace-with-password",
]);
$checksum = bbbChecksum("create", $params, $bbbSecret);
$response = file_get_contents("{$bbbUrl}/create?{$params}&checksum={$checksum}");
echo $response;

JavaScript (Node.js)

const crypto = require("crypto");
const https = require("https");

const BBB_URL = "https://api-guide.bbbserver.com/bigbluebutton/api";
const BBB_SECRET = "replace-with-secret";

function bbbChecksum(callName, queryString) {
  return crypto
    .createHash("sha256")
    .update(callName + queryString + BBB_SECRET)
    .digest("hex");
}

// Create a meeting
const params = new URLSearchParams({
    name: "Demo",
    meetingID: "replace-with-meeting-id",
    attendeePW: "replace-with-password",
    moderatorPW: "replace-with-password",
}).toString();

const checksum = bbbChecksum("create", params);
https.get(`${BBB_URL}/create?${params}&checksum=${checksum}`, (res) => {
  let data = "";
  res.on("data", (chunk) => (data += chunk));
  res.on("end", () => console.log(data));
});

Java

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public class BbbApi {
    static final String BBB_URL = "https://api-guide.bbbserver.com/bigbluebutton/api";
    static final String BBB_SECRET = "replace-with-secret";

    static String bbbChecksum(String callName, String queryString) throws Exception {
        String raw = callName + queryString + BBB_SECRET;
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(raw.getBytes(StandardCharsets.UTF_8));
        StringBuilder hex = new StringBuilder();
        for (byte b : hash) hex.append(String.format("%02x", b));
        return hex.toString();
    }

    public static void main(String[] args) throws Exception {
        String params = "name=" + URLEncoder.encode("Demo", "UTF-8")
            + "&meetingID=replace-with-meeting-id"
            + "&attendeePW=replace-with-password"
            + "&moderatorPW=replace-with-password";
        String checksum = bbbChecksum("create", params);
        String url = BBB_URL + "/create?" + params + "&checksum=" + checksum;
        System.out.println(url);
    }
}

Ruby

require "digest"
require "uri"
require "net/http"

BBB_URL    = "https://api-guide.bbbserver.com/bigbluebutton/api"
BBB_SECRET = "replace-with-secret"

def bbb_checksum(call_name, query_string)
  Digest::SHA256.hexdigest(call_name + query_string + BBB_SECRET)
end

# Create a meeting
params = URI.encode_www_form(
    name: "Demo",
    meetingID: "replace-with-meeting-id",
    attendeePW: "replace-with-password",
    moderatorPW: "replace-with-password"
)
checksum = bbb_checksum("create", params)
uri = URI("#{BBB_URL}/create?#{params}&checksum=#{checksum}")
puts Net::HTTP.get(uri)

curl (Bash)

BBB_URL="https://api-guide.bbbserver.com/bigbluebutton/api"
BBB_SECRET="replace-with-secret"

CALL="create"
PARAMS="name=Demo&meetingID=replace-with-meeting-id&attendeePW=replace-with-password&moderatorPW=replace-with-password"
CHECKSUM=$(echo -n "${CALL}${PARAMS}${BBB_SECRET}" | sha256sum | awk '{print $1}')

curl -s "${BBB_URL}/${CALL}?${PARAMS}&checksum=${CHECKSUM}"

Vollständiges Beispiel: Ein Meeting erstellen und beitreten (curl)

#!/bin/bash
BBB_URL="https://api-guide.bbbserver.com/bigbluebutton/api"
BBB_SECRET="replace-with-secret"

bbb_checksum() {
  echo -n "${1}${2}${BBB_SECRET}" | sha256sum | awk '{print $1}'
}

# 1. Create a meeting
CREATE_PARAMS="name=Demo&meetingID=replace-with-meeting-id&attendeePW=replace-with-password&moderatorPW=replace-with-password"
CREATE_CS=$(bbb_checksum "create" "$CREATE_PARAMS")
curl -s "${BBB_URL}/create?${CREATE_PARAMS}&checksum=${CREATE_CS}"

# 2. Generate moderator join URL
JOIN_PARAMS="meetingID=replace-with-meeting-id&fullName=Admin&role=MODERATOR&redirect=true"
JOIN_CS=$(bbb_checksum "join" "$JOIN_PARAMS")
echo ""
echo "Moderator URL: ${BBB_URL}/join?${JOIN_PARAMS}&checksum=${JOIN_CS}"

# 3. Generate viewer join URL
JOIN_PARAMS2="meetingID=replace-with-meeting-id&fullName=Guest&role=VIEWER&redirect=true"
JOIN_CS2=$(bbb_checksum "join" "$JOIN_PARAMS2")
echo "Viewer URL: ${BBB_URL}/join?${JOIN_PARAMS2}&checksum=${JOIN_CS2}"

# 4. Check meeting status
INFO_CS=$(bbb_checksum "getMeetingInfo" "meetingID=replace-with-meeting-id")
curl -s "${BBB_URL}/getMeetingInfo?meetingID=replace-with-meeting-id&checksum=${INFO_CS}"

Häufig gestellte Fragen

Die Prüfsumme ist ein kryptografischer Hash, der an jede API-Anfrage angehängt wird. Sie beweist, dass der Aufrufer das Shared Secret kennt, ohne das Secret selbst zu übertragen. Ohne eine gültige Prüfsumme lehnt der BigBlueButton-Server die Anfrage ab.

Verwenden Sie SHA-256 oder höher für alle neuen Implementierungen. SHA-1 wird aus Gründen der Abwärtskompatibilität unterstützt, gilt jedoch als veraltet. SHA-384 und SHA-512 sind ab BigBlueButton 2.5 verfügbar.

Nein. Die Prüfsumme wird ausschließlich aus dem URL-Query-String berechnet. Der POST-Body (wie Präsentations-XML oder Client-Settings-Overrides) wird nicht in die Berechnung der Prüfsumme einbezogen.

Führen Sie den Befehl bbb-conf --setsecret <new-secret> auf Ihrem BigBlueButton-Server aus. Nachdem Sie das Secret geändert haben, aktualisieren Sie sofort alle integrierenden Anwendungen, da das alte Secret nicht mehr akzeptiert wird.

Ja. Bearbeiten Sie die Eigenschaft supportedChecksumAlgorithms in /etc/bigbluebutton/bbb-web.properties und entfernen Sie die Algorithmen, die Sie deaktivieren möchten. Wenn Sie SHA-256 deaktivieren, aktualisieren Sie auch die Einstellung checkSumAlgorithmForBreakouts in bbb-apps-akka.conf.

Da die Prüfsumme das Shared Secret als Teil der Eingabe für den Hash enthält, erzeugt jede Änderung an den Query-Parametern einen anderen Hash. Der Server berechnet die Prüfsumme seinerseits neu und lehnt die Anfrage ab, wenn die Werte nicht übereinstimmen.

Nein. Der Mechanismus der Prüfsumme enthält standardmäßig weder einen Zeitstempel noch eine Nonce. Um Replay-Angriffe auf Join-URLs zu entschärfen, fügen Sie den Parameter createTime aus der ursprünglichen create-Antwort ein. Dadurch wird der Join-Link an eine bestimmte Meeting-Instanz gebunden.