Zum Hauptinhalt springen

Authentifizierung

An authentication gate plugin makes viewers sign in before reaching the resources selected by the server operator. The plugin supplies the login method, such as OAuth, a magic link, SAML, or a shared password. Owncast enforces the selected access mode.

  • Ihr Plugin ist der Identitätsanbieter. Es zeigt den Anmeldebildschirm an, kommuniziert mit dem externen Anbieter und entscheidet, wer hereingelassen wird.
  • The Owncast host is the gatekeeper and session authority. It owns the session cookie, enforces the selected access mode, and never puts your plugin in the per-request hot path.
Owncat informs you

Alles auf dieser Seite benötigt die Erlaubnis auth.gate, plus users.register, um den authentifizierten Benutzer zu erstellen und http.serve, um den Anmeldeablauf darzustellen.

Was wird abgesichert

When an auth.gate plugin is enabled, the viewer page, chat, embeds, /api/config, and the rest of the public web surface require login. A short list of routes stays public in every mode, including Owncast's admin pages (they keep their own admin authentication, so an operator can always disable a broken gate), the instance logo, and the ActivityPub federation endpoints. See what bypasses the gate for the full list.

The operator selects one cumulative access mode on the plugin's Authentication tab:

Access modeEffect
Website only (default)The web interface requires sign-in. /hls/*, /api/status, and Owncast Directory listing stay public.
Website, video players, and other resourcesAlso gates Owncast-hosted /hls/*. Players such as VLC cannot complete the browser login. /api/status and directory listing stay public.
Website, video players, and server status requestsGates the web interface, Owncast-hosted /hls/*, and /api/status. Owncast Directory listing is disabled.

The modes are cumulative. There is no status-only mode that hides /api/status while leaving HLS public. The default protects the website without breaking existing players or uptime monitors.

Selecting either stream-protection mode blocks native players. VLC, QuickTime, mobile apps, and restreamers cannot complete a browser login or carry the session cookie. An Authorization header or query token does not bypass the gate.

A viewer with a valid session is always let through, regardless of the selected mode.

Owncat warns youHinweis zur Verteilung Ihres Videos mit externem Speicher (Objektspeicher/CDN)

When distributing your video stream directly from your server, stream protection is airtight: every byte flows through Owncast. Mit Objektspeicher oder CDN werden Playlists in absolute Remote-URLs umgeschrieben und Segmente direkt aus dem Bucket abgerufen, sodass das Tor diese Anfragen niemals sieht. Die Sicherung stoppt immer noch einen anonymen Besucher daran, die Segmentliste zu entdecken, aber eine geleakte oder geteilte Segment-URL bleibt abrufbar. Stream protection + local distribution is airtight. Stream protection + Object Storage is good friction, not airtight.

Wie es funktioniert

Once the gate is armed, every non-exempt request is checked. Under stream protection that includes each HLS segment, which a live viewer pulls every few seconds. Jede dieser Anfragen an die eingebaute Engine Ihres Plugins würde den Server überlasten, sodass das Plugin vom heißen Pfad ferngehalten wird:

WennKostenWas passiert
Every non-exempt requestÜberprüfen Sie die Cookie-Signatur + das Ablaufdatumvalid passes. Missing or invalid gets a redirect to login, or a 401 for anything that is not a GET or HEAD
/-Seite lädt nurOptionale Engine-Anfrage: onAuthCheckerneut gegen Ihren Anbieter validieren, gibt ok / refresh / deny zurück

Ihr Plugin führt nur den Anmeldeablauf aus (selten, etwa einmal pro Zuschauersitzung) und die optionale onAuthCheck pro Seitenlade-Anfrage. Der Owncast-Host erstellt und überprüft ein unterschriebenes Sitzungscookie, sodass die Überprüfung pro Anfrage nur auf Signatur und Ablauf basiert: kein Datenbankaufruf, kein Pluginaufruf.

The cookie is a signed envelope carrying an Owncast access token plus a session expiry. The host mints a fresh access token for the user each time it grants a session. The Owncast host owns the cookie end to end: it reserves the cookie name (owncast_session), signs it with a host-held secret, and attaches it to the response. Ihr Plugin sieht oder setzt das Token niemals, sodass es kein Token fälschen oder leaken kann. (So erdet auch der Chat automatisch die Identität des Zuschauers. Siehe Chat-Identität weiter unten.)

Erstellen eines Tor-Plugins

Ein Tor-Plugin ist ein HTTP-dienendes Plugin mit einem Anmeldeablauf. Der Steuerkreis ist nach Konvention im Namensraum des Plugins /plugins/\<your-slug>/ verwurzelt:

Drei Teile erledigen die Arbeit:

  1. Registrieren Sie den Benutzer. Machen Sie die externe Identität zu einem echten Owncast-Benutzer mit owncast.users.register. Geben Sie eine stabile, anbieterübergreifende authId (z. B. "github:583231"). Der Host benennt es mit Ihrem Slug, sodass Plugins einander nicht kollidieren oder sich nachahmen können.
  2. Genehmigen Sie die Sitzung. Rufen Sie owncast.auth.grantSession mit dieser userId auf. Der Owncast-Host erstellt das unterschriebene Cookie und hängt es an die in Bearbeitung befindliche Antwort an. Dies funktioniert nur innerhalb eines onHttpRequest-Handlers.
  3. Umleiten zur Startseite. Der Owncast-Host fügt einen return_to-Abfrageparameter hinzu, wenn er einen nicht authentifizierten Besucher auf Ihren Anmeldebildschirm umleitet, und sanifiziert ihn zu einem Pfad mit derselben Herkunft (damit er nicht in eine offene Umleitung verwandelt werden kann). Senden Sie den Zuschauer nach einer erfolgreichen Anmeldung dorthin.

Um einen Zuschauer abzumelden, rufen Sie owncast.auth.endSession() auf und leiten Sie um. Ihr Plugin steuert weiterhin, wohin (es kann auf die Abmeldung des Anbieters umgleiten).

Widerruf mit onAuthCheck

Sitzungen sind zustandslos, daher gibt es keine pro Anfrage-Liste "Darf dieser Benutzer weiterhin". Das würde das Plugin wieder auf den heißen Weg setzen. Definieren Sie stattdessen den optionalen onAuthCheck Handler. Es wird bei jedem /-Seitenaufruf mit der gelösten Zuschaueridentität ausgelöst und gibt ok, refresh (erneuerung des Cookies, optional mit einer neuen TTL für gleitende Abläufe) oder deny (sitzung beenden und umleiten zur Anmeldung) zurück. Ein anbieterübergreifendes Plugin überprüft hier die Mitgliedschaft erneut (ist die Organisation weiterhin gültig? Wurde das Konto nicht gelöscht?).

Da die Überprüfung nur auf / ausgeführt wird, behält ein Zuschauer, dem Sie die Berechtigung entziehen, jede offene Registerkarte funktionstüchtig, bis er aktualisiert oder das Cookie abläuft. Die Sitzung TTL ist das harte Sicherheitsnetz für den Widerruf, also halten Sie sie kurz, wenn eine schnelle Widerrufung wichtig ist.

Beispiel: ein Passworttor

Das Plugin-Beispiel basic-auth ist das einfachste mögliche Tor: ein gemeinsames Passwort, eine gemeinsame "Gast"-Identität, kein externer Anbieter. Es wird sowohl in examples/js/basic-auth als auch in examples/python/basic-auth geliefert.

Sein Manifest erklärt die Berechtigungen und ein einzelnes Konfigurationsfeld für das Passwort:

{
"name": "Basic Auth",
"slug": "basic-auth",
"version": "0.1.0",
"permissions": ["auth.gate", "users.register", "http.serve", "storage.kv"],
"config": {
"password": {
"type": "string",
"default": "letmein",
"description": "Shared password viewers must enter to watch"
}
}
}

Der Handler rendert ein Passwortformular auf /, überprüft das eingegebene Passwort mit dem konfigurierten Wert und registriert bei Erfolg die gemeinsame Identität, gewährt eine Sitzung und leitet zurück um. onAuthCheck liest ein von Administratoren umschaltbares revoked-Flag, um alle bei ihrem nächsten Seitenaufruf auszuschließen. (Der page()-Helper, der das HTML-Formular erstellt, wird der Kürze halber unten weggelassen. Siehe den Beispiel-Quellcode.)

const { definePlugin, owncast, authCheck } = require('@owncast/plugin-sdk');

module.exports = definePlugin({
onHttpRequest(req) {
const query = req.query || {};
const returnTo = query.return_to || '/';

if (req.method === 'GET' && req.path === '/') {
return {
status: 200,
headers: { 'content-type': 'text/html' },
body: page(returnTo),
};
}

if (req.path === '/login') {
const expected = owncast.config.get('password', 'letmein');
if ((query.password || '') !== expected) {
return {
status: 200,
headers: { 'content-type': 'text/html' },
body: page(returnTo, 'Incorrect password.'),
};
}
// Everyone who knows the password shares one authenticated identity.
const { userId } = owncast.users.register({
authId: 'shared',
displayName: 'Guest',
});
owncast.auth.grantSession({ userId });
return { status: 302, headers: { Location: returnTo } };
}

if (req.path === '/logout') {
owncast.auth.endSession();
return { status: 302, headers: { Location: '/' } };
}

// Admin-only revocation toggle. req.authenticated is true for admins only.
if (req.path === '/revoke' || req.path === '/unrevoke') {
if (!req.authenticated) return { status: 403, body: 'admin only' };
owncast.kv.set('revoked', req.path === '/revoke' ? '1' : '');
return {
status: 200,
body: req.path === '/revoke' ? 'revoked' : 'unrevoked',
};
}

return { status: 404, body: 'not found' };
},

// Re-validate on each page load. While revoked, end every session.
onAuthCheck() {
if (owncast.kv.get('revoked') === '1') return authCheck.deny('access has been revoked');
return authCheck.ok();
},
});

Für einen echten OAuth-Fluss (CSRF state in storage.kv, ein Code-Austausch über network.fetch, Durchsetzung der Mitgliedschaft und eine Callback-URL, die aus owncast.server.info() erstellt wurde), siehe das Beispiel github-auth im SDK.

Das Tor aktivieren

Die Deklaration von auth.gate hat von sich aus keine Wirkung. Das Tor wird aktiviert, indem das Plugin über den normalen Lebenszyklus aktiv/passiv im Admin-Bereich aktualisiert wird. Deaktivieren Sie es und das Tor fällt sofort.

  • Es kann immer nur ein auth.gate-Plugin gleichzeitig aktiviert sein. Owncast verweigert die Aktivierung eines zweiten, solange eines bereits aktiv ist ("deaktivieren Sie zuerst das andere").
  • Konfigurieren Sie, bevor Sie aktivieren. Ein Plugin kann installiert und konfiguriert werden, während es deaktiviert ist, und dann aktiviert werden, um live zu gehen. Verwenden Sie das automatisch generierte Konfigurationsformular für Anmeldeinformationen wie eine OAuth-Client-ID und ein Geheimnis.

Falls geschlossen

Die Haltung des Tors ist von der Gesundheit Ihres Plugins entkoppelt. Wenn das Tor aktiviert ist, aber das Plugin nicht verfügbar ist (abgestürzt, fehlgeschlagen, Fehler, oder nach wiederholtem Fehlschlagen automatisch deaktiviert), lehnt Owncast allen Zuschauerverkehr ab und zeigt eine statische "Authentifizierung vorübergehend nicht verfügbar"-Seite an. Es öffnet sich nie. Der Administrator ist immer erreichbar (Admin-Routen verwenden die vorhandene Basis-Authentifizierung von Owncast und umgehen das Tor), sodass Sie die Konfiguration beheben oder das Plugin deaktivieren können. Bereits gültige Sitzungen überstehen einen Ausfall, da die Überprüfung eines Cookies keinen Pluginaufruf benötigt.

A gate that is enabled but not running is still a gate. No access-policy setting can turn a failing-closed gate into an open one.

Was das Tor umgeht

The gate covers the otherwise-public surface. Routes that enforce their own credentials bypass it. The selected access mode also leaves some resources public.

Always exempt:

  • The active gate plugin's own namespace /plugins/\<your-slug>/* and its static assets, so the login screen remains reachable.
  • /admin/* and /api/admin/*, which use admin authentication.
  • External API routes under /api/integrations/, which validate their own Bearer tokens.
  • Static viewer assets needed to render the page. HTML entry points are still gated.
  • /api/yp, which the Owncast Directory fetches anonymously. The most restrictive mode disables directory listing and makes this endpoint return 404.
  • /logo and /logo/external, the instance logo, which the viewer shell and federation metadata both reference.
  • /federation/*, the ActivityPub protocol surface. Those handlers enforce Owncast's own federation and privacy settings.

Mode-dependent:

  • /hls/* stays public only in Website only mode.
  • /api/status stays public in Website only and Website, video players, and other resources modes.

Everything else is gated, including embeds and /api/config.

Sitzungsdetails

  • Stateless signed cookie named owncast_session, HttpOnly, Secure (on HTTPS requests), SameSite=Lax, Path=/. Lax statt Strict, da der Callback des Anbieters eine cross-site top-level Umleitung ist. The host owns the name: a plugin that tries to set it in its own response has that header stripped.
  • TTL is set by your plugin when it calls grantSession({ ttl }), defaulting to 24 hours and capped at 30 days. A sliding refresh is available through onAuthCheck's refresh verdict. Da die TTL das Sicherheitsnetz für den Widerruf ist, ist es ein echtes Sicherheitsinstrument.
  • Das Geheimnis der Signatur liegt in der Verantwortung des Owncast-Hosts. Es wird bei der ersten Verwendung automatisch generiert und in der Konfiguration gespeichert. Die Rotation macht jede Sitzung ungültig (einen Panik-Button). Plugin-Autoren berühren es nie, und es ist unabhängig von einem OAuth-Client-Geheimnis, was die Konfiguration Ihres Plugins betrifft.

Chat-Identität

Ein Toranmeldung erzeugt automatisch eine authentifizierte Chat-Identität. Because users.register creates or links a real Owncast user (marked authenticated, with the display name you passed, or a generated one if you passed none) and the session cookie carries an access token for that user, chat reads the identity straight from the cookie: when /ws (or a chat REST call) arrives with no ?accessToken= query parameter, it falls back to the access token in the gate cookie. Kein Token wird jemals in den localStorage des Browsers transportiert. The viewer signs in once and shows up in chat under that name.

Verwandt


Improve this page

See something missing or incorrect? Edit the English version of this page or help improve translations.

Contributors to this documentation