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,reportsundproject, 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.pemEC 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.pemUm 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_credentialsMit 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:
| Feld | Wert |
|---|---|
Kopfzeile alg | EdDSA, ES256 oder RS256, passend zum Schlüssel |
Kopfzeile kid | Die ID des registrierten Schlüssels |
iss und sub | Die Client-ID |
aud | https://api.screenrig.ai oder https://api.screenrig.ai/oauth/token, als ein String |
iat, exp | Maximal 5 Minuten Abstand |
jti | Ein 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:readoderaccess:proposegibt dem Token ein niedrigeres Level als dem des Clients, und Fähigkeitsnamen behalten nur diese Fähigkeiten, zum Beispielscope=access:read reports. Ein Bereich über den des Clients hinaus istinvalid_scope.resource:https://api.screenrig.ai/api, der Standard, für die REST-API, oderhttps://api.screenrig.ai/mcpfü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 listVerwenden 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
| Bis | Dashboard (Zugriff, der Client) | CLI |
|---|---|---|
| Einen zweiten Schlüssel hinzufügen | Schlüssel hinzufügen | screenrig service-client add-key scl_ID --key-file new.pem |
| Schlüssel entfernen | Schlüssel entfernen | screenrig service-client remove-key scl_ID --kid KID |
| Ein zweites Geheimnis hinzufügen | Geheimnis generieren | screenrig service-client add-secret scl_ID --secret-file new-secret |
| Geheimnis entfernen | Geheimnis entfernen | screenrig service-client remove-secret scl_ID --secret-id css_ID |
| Zugriff oder Berechtigungen ändern | Zugriff, dann Zugriff speichern | Verwenden Sie das Dashboard |
| Client beenden | Widerrufen | screenrig 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
| Antwort | Ursache | Beheben |
|---|---|---|
401 invalid_client | Falsches oder entferntes Geheimnis, eine schlechte oder wiederholte Behauptung, ein unbekannter kid, ein widerrufener Client oder ein abgebrochenes oder gelöschtes Projekt | Prüfen Sie die Anmeldeinformationen gegen service-client show; senden Sie jedes Mal ein frisches jti |
400 invalid_scope | Ein Bereich außerhalb des Zugriffs oder der Fähigkeiten des Clients | Weniger verlangen oder den Client wechseln |
400 invalid_target | Ein resource außer den beiden aufgeführten | Verwenden Sie den Standard- oder den Remote-Server |
429 rate_limited | Mehr als 600 Token pro Client oder 1.200 Token-Anfragen pro Adresse innerhalb einer Stunde | Token bis zum Ablauf wiederverwenden |
503 temporarily_unavailable | Versuchen Sie es in Kürze erneut | Erneut versuchen mit Rückoff |
401 von /api | Das Token ist abgelaufen oder wurde widerrufen. | Bitten Sie einmal um ein neues Token, dann stoppen |
403 forbidden beim Verwalten von Clients | Es fehlt die Identitätsberechtigung, eine aktuelle Projektmitgliedschaft mit der Fähigkeit project oder die Organisationsadministratorrolle der verantwortlichen Person | Die 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 /api | Das 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 /api | Das Projekt hat kein Guthaben für eine kostenpflichtige Anfrage | Projektguthaben hinzufügen |