Dokumentation

Geben Sie Servern und CI-Jobs ihren eigenen Zugang

Ein Service-Client ist ein Server, Skript oder CI-Job, der mit eigenen Anmeldeinformationen an einem Projekt arbeitet. Er meldet sich mit einem privaten Schlüssel oder einem Secret an, erhält ein 15-minütiges Zugriffstoken und benötigt nie die Genehmigung einer Person für jeden Lauf.

Was ein Service-Client ist

  • Im Projektbesitz. Das Projekt behält den Client, wenn die Person oder der Agent, der es erstellt hat, das Projekt verlässt. Seine Anfragen werden als Agentenanfragen in Rechnung gestellt, basierend auf den gleichen inkludierten Anfragen.
  • Nur lesen, Vorschlagen oder Verwalten. Wird bei der Erstellung wie ein angemeldeter Agent festgelegt. Nur lesen listet auf und liest; Vorschlagen lädt auch Medien hoch und schlägt Playlist- und Bildschirmänderungen zur Überprüfung durch eine Person vor; Verwalten ändert, veröffentlicht und gibt auch aus. Wenn das Projekt eine Überprüfung von Agentenänderungen erfordert, arbeitet ein Client höchstens im Modus Vorschlagen. Siehe Nur lesen, Vorschlagen und Verwalten.
  • Fähigkeiten. Jedes von screens, content, playlists, advertising, reports und project, innerhalb der eigenen des Erstellers.
  • Begrenzt. Ein Service-Client erstellt oder verwaltet niemals Service-Clients, Mitglieder, Einladungen oder Agent-Anmeldungen.
  • Zwei Anmeldemöglichkeiten. Ein registrierter öffentlicher Schlüssel (private_key_jwt, der empfohlene Weg) oder ein Geheimnis (client_secret_basic). Ein Client kann bis zu zwei von jedem halten, sodass Sie ohne Ausfallzeiten rotieren können.

Eine Organisation enthält bis zu 50 Live-Service-Clients über alle ihre Projekte. Client-IDs beginnen mit scl_ und Geheimnisse mit sr_cs_.

Schlüssel erstellen

Ein Ed25519-Schlüsselpaar auf der Maschine erzeugen, die den Client ausführt. Der private Schlüssel verlässt diese nie; screenRIG speichert nur den öffentlichen Teil.

openssl genpkey -algorithm ed25519 -out screenrig-client.pem
chmod 600 screenrig-client.pem

EC P-256-Schlüssel und RSA-Schlüssel mit mindestens 2048 Bit funktionieren ebenfalls.

Client erstellen

Im Dashboard. Öffnen Sie Zugriff und wählen Sie Neuer Service-Client. Benennen Sie ihn, wählen Sie Nur lesen, Vorschlagen oder Verwalten, prüfen Sie die Berechtigungen und fügen Sie den öffentlichen Schlüssel als JWK ein oder wählen Sie Client-Geheimnis generieren. Drucken Sie den öffentlichen JWK Ihres Schlüssels mit Node aus:

node -e 'const c=require("node:crypto");const k=c.createPublicKey(require("node:fs").readFileSync("screenrig-client.pem"));console.log(JSON.stringify(k.export({format:"jwk"})))'

Mit der CLI. Der Agent benötigt Manage-Zugriff für seine Identität mit dem Geltungsbereich identity, eine eigene Manage-Berechtigung mit der Fähigkeit project im Zielprojekt und eine verifizierte verantwortliche Person, die die Organisation dieses Projekts verwaltet.

Bei einem neu registrierten Agenten muss die eingeladene Person zuerst die Registrierungseinladung annehmen. Manage-Zugriff auf das Projekt allein berechtigt nicht zu Änderungen an Zugangsdaten.

--key-file akzeptiert eine JWK- oder PEM-Datei und sendet nur deren öffentlichen Teil:

screenrig service-client create --name "Nightly report" --access read \
  --capability reports --key-file screenrig-client.pem

Um stattdessen ein Geheimnis zu verwenden, fügen Sie --secret-file PATH hinzu. Die CLI schreibt das Geheimnis mit Modus 0600 in diese neue Datei; es wird einmal angezeigt und nie wieder.

screenrig service-client show scl_ID listet die Schlüssel-IDs des Clients (kid) und die Geheim-IDs. Ein Schlüssel ohne eigenen kid ist durch seinen RFC 7638 Fingerabdruck bekannt.

Uploader-Clients

Der Agent einer Agentur erhält einen Client, der auf ausgewählte Playlists und Medienordner beschränkt ist: Fügen Sie --uploader --folder-id mfd_FOLDER[,mfd_FOLDER] --playlist-id pl_PLAYLIST[,pl_PLAYLIST] zu service-client create hinzu. Ein Uploader-Client hat nur die Berechtigungen content und playlists und handelt mit Vorschlagen, sofern --access nichts anderes angibt. Mit seinem Token lädt er in seine Ordner hoch (screenrig media upload FILE --folder mfd_FOLDER) und fügt Seiten seiner Playlists hinzu, ersetzt und entfernt sie (screenrig playlist page add|replace|remove); alles andere antwortet mit outside_upload_scope, dessen upload_scope auflistet, was er verwenden darf. Der Projekteigentümer ändert die Ordner und Playlists eines Clients später; eine Änderung gilt für das bereits ausgestellte Token. Siehe Uploader.

Zugangstoken erhalten

Bitten Sie den Token-Endpunkt um ein Token mit dem client_credentials-Grant. Die Antwort enthält access_token, token_type: Bearer, expires_in (900 Sekunden) und scope. Es gibt kein Refresh-Token: Bitten Sie erneut, wenn es abläuft.

Mit einem Geheimnis authentifizieren Sie sich mit HTTP Basic. Ein Geheimnis im Anfragetext wird abgelehnt:

curl -s https://api.screenrig.ai/oauth/token \
  -u "$SCREENRIG_CLIENT_ID:$SCREENRIG_CLIENT_SECRET" \
  -d grant_type=client_credentials

Mit einem Schlüssel senden Sie eine signierte Client-Assertion anstelle eines Geheimnisses:

curl -s https://api.screenrig.ai/oauth/token \
  -d grant_type=client_credentials \
  -d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
  -d client_assertion="$ASSERTION"

Die Behauptung ist ein JWT, das mit Ihrem privaten Schlüssel signiert ist:

FeldWert
Kopfzeile algEdDSA, ES256 oder RS256, passend zum Schlüssel
Kopfzeile kidDie ID des registrierten Schlüssels
iss und subDie Client-ID
audhttps://api.screenrig.ai oder https://api.screenrig.ai/oauth/token, als ein String
iat, expMaximal 5 Minuten Abstand
jtiEin neuer Zufallswert für jede Assertion; eine Wiederholung wird abgelehnt

Kopfzeilen jku, x5u, jwk und x5c werden abgelehnt.

Weniger verlangen

Zwei optionale Parameter schränken ein Token ein:

  • scope: access:read oder access:propose gibt dem Token ein niedrigeres Level als dem des Clients, und Fähigkeitsnamen behalten nur diese Fähigkeiten, zum Beispiel scope=access:read reports. Ein Bereich über den des Clients hinaus ist invalid_scope.
  • resource: https://api.screenrig.ai/api, der Standard, für die REST-API, oder https://api.screenrig.ai/mcp für den Remote-Server.

API aufrufen

Senden Sie das Token als Bearer. Es wirkt auf das eigene Projekt des Clients:

curl -s https://api.screenrig.ai/api/screens \
  -H "Authorization: Bearer $TOKEN"

Node: Ein zwischengespeichertes Token mit einem Schlüssel

Dieser Helfer signiert die Assertion mit Nodes eingebauter Kryptografie, hält das Token im Speicher und fordert eine neue eine Minute vor Ablauf an. Setzen Sie CLIENT_KEY_ID auf den Schlüssel-kid aus service-client show:

import { createPrivateKey, randomUUID, sign } from "node:crypto";
import { readFileSync } from "node:fs";

const ISSUER = "https://api.screenrig.ai";
const { SCREENRIG_CLIENT_ID: clientId, SCREENRIG_CLIENT_KEY_FILE: keyFile, CLIENT_KEY_ID: kid } = process.env;
const key = createPrivateKey(readFileSync(keyFile));
const part = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
let cached;

function assertion() {
  const now = Math.floor(Date.now() / 1000);
  const input = `${part({ alg: "EdDSA", typ: "JWT", kid })}.${part({ iss: clientId, sub: clientId, aud: ISSUER, iat: now, exp: now + 60, jti: randomUUID() })}`;
  return `${input}.${sign(null, Buffer.from(input), key).toString("base64url")}`;
}

export async function accessToken() {
  if (cached && cached.expiresAt - 60_000 > Date.now()) return cached.token;
  const response = await fetch(`${ISSUER}/oauth/token`, {
    method: "POST",
    body: new URLSearchParams({
      grant_type: "client_credentials",
      client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
      client_assertion: assertion(),
    }),
  });
  const body = await response.json();
  if (!response.ok) throw new Error(`screenRIG token request refused: ${body.error}: ${body.error_description ?? ""}`);
  cached = { token: body.access_token, expiresAt: Date.now() + body.expires_in * 1000 };
  return cached.token;
}

Python: ein zwischengespeicherter Token mit einem Geheimnis

import base64, json, os, time, urllib.parse, urllib.request

ISSUER = "https://api.screenrig.ai"
_cached = {"token": None, "expires_at": 0.0}


def access_token() -> str:
    if _cached["token"] and _cached["expires_at"] - 60 > time.time():
        return _cached["token"]
    pair = f'{os.environ["SCREENRIG_CLIENT_ID"]}:{os.environ["SCREENRIG_CLIENT_SECRET"]}'
    request = urllib.request.Request(
        f"{ISSUER}/oauth/token",
        data=urllib.parse.urlencode({"grant_type": "client_credentials"}).encode(),
        headers={"Authorization": "Basic " + base64.b64encode(pair.encode()).decode()},
    )
    with urllib.request.urlopen(request, timeout=10) as response:
        body = json.load(response)
    _cached.update(token=body["access_token"], expires_at=time.time() + body["expires_in"])
    return body["access_token"]

Führen Sie die CLI als Service-Client aus

Melden Sie die CLI einmal als Client an, in einer eigenen Konfiguration. Die Konfiguration hält den Client und die Datei fest, die seinen privaten Schlüssel (empfohlen) oder sein Geheimnis enthält, nie den Schlüssel oder das Geheimnis selbst:

screenrig --config /run/screenrig/ci.json login --client-id scl_ID \
  --client-key-file /run/secrets/screenrig-client.pem
screenrig --config /run/screenrig/ci.json screen list

Verwenden Sie --client-secret-file FILE statt --client-key-file für ein Geheimnis. Jeder Befehl mit dieser Konfiguration wird als der Client ohne Anmeldeschritt ausgeführt: Er liest die Schlüssel- oder Geheimnisdatei jedes Mal neu (eine rotierte Datei braucht daher keine neue Anmeldung), hält das Token im Speicher und schreibt sonst nichts in die Konfiguration. screenrig logout entfernt den Client daraus. Jeder Befehl fordert sein eigenes Token an, daher ist ein Job, der mehr als ein paar hundert Befehle pro Stunde ausführt, mit einem über die API wiederverwendeten Token besser bedient.

Rotieren und widerrufen

BisDashboard (Zugriff, der Client)CLI
Einen zweiten Schlüssel hinzufügenSchlüssel hinzufügenscreenrig service-client add-key scl_ID --key-file new.pem
Schlüssel entfernenSchlüssel entfernenscreenrig service-client remove-key scl_ID --kid KID
Ein zweites Geheimnis hinzufügenGeheimnis generierenscreenrig service-client add-secret scl_ID --secret-file new-secret
Geheimnis entfernenGeheimnis entfernenscreenrig service-client remove-secret scl_ID --secret-id css_ID
Zugriff oder Berechtigungen ändernZugriff, dann Zugriff speichernVerwenden Sie das Dashboard
Client beendenWiderrufenscreenrig service-client revoke scl_ID --yes

Um ohne Ausfallzeit zu rotieren, fügen Sie den neuen Schlüssel oder das neue Geheimnis hinzu, setzen Sie es ein und entfernen Sie dann den alten. Tokens, die mit einem entfernten Schlüssel oder Geheimnis ausgestellt wurden, funktionieren innerhalb von Sekunden nicht mehr, und ein Client behält mindestens einen Schlüssel oder ein Geheimnis.

Die Einschränkung des Zugriffs oder der Fähigkeiten eines Clients beendet seine aktuellen Tokens; sein nächstes Token trägt den neuen Zugriff. Das Widerrufen ist dauerhaft: Die Schlüssel und Geheimnisse werden gelöscht, die Tokens des Clients funktionieren innerhalb von Sekunden nicht mehr, und der Eintrag bleibt zur Prüfung auf der Zugriffsseite erhalten. Das Löschen des Projekts widerruft seine Clients.

Ein Client erhält Tokens nur, solange sein Projekt aktiv ist. Ein storniertes oder gelöschtes Projekt gibt keine aus. Ein Projekt mit null Guthaben gibt weiterhin Tokens aus, und seine bezahlten Anfragen antworten wie ein Agent mit 402 payment_required.

Fehler und Limits

AntwortUrsacheBeheben
401 invalid_clientFalsches oder entferntes Geheimnis, eine schlechte oder wiederholte Behauptung, ein unbekannter kid, ein widerrufener Client oder ein abgebrochenes oder gelöschtes ProjektPrüfen Sie die Anmeldeinformationen gegen service-client show; senden Sie jedes Mal ein frisches jti
400 invalid_scopeEin Bereich außerhalb des Zugriffs oder der Fähigkeiten des ClientsWeniger verlangen oder den Client wechseln
400 invalid_targetEin resource außer den beiden aufgeführtenVerwenden Sie den Standard- oder den Remote-Server
429 rate_limitedMehr als 600 Token pro Client oder 1.200 Token-Anfragen pro Adresse innerhalb einer StundeToken bis zum Ablauf wiederverwenden
503 temporarily_unavailableVersuchen Sie es in Kürze erneutErneut versuchen mit Rückoff
401 von /apiDas Token ist abgelaufen oder wurde widerrufen.Bitten Sie einmal um ein neues Token, dann stoppen
403 forbidden beim Verwalten von ClientsEs fehlt die Identitätsberechtigung, eine aktuelle Projektmitgliedschaft mit der Fähigkeit project oder die Organisationsadministratorrolle der verantwortlichen PersonDie eingeladene Person muss die Registrierung annehmen; prüfen Sie den Manage-Zugriff für die Identität, die eigene Manage-Berechtigung des Agenten im Projekt und die Organisationsadministratorrolle der verantwortlichen Person
403 insufficient_access von /apiDas Zugriffslevel des Tokens kann diese Änderung nicht vornehmen oder das Projekt erfordert eine Überprüfung für Agentenänderungen.Verwenden Sie einen Manage-Client; während das Projekt eine Überprüfung erfordert, gehen Playlist- und Bildschirmänderungen zu Reviews
402 payment_required von /apiDas Projekt hat kein Guthaben für eine kostenpflichtige AnfrageProjektguthaben hinzufügen