Zum Inhalt springen

Delegierter Zugang mit OAuth 2.1

Ihre Anwendung läuft bei fremden Kunden: registrieren, mit PKCE einwilligen lassen, Token oat_ tauschen, erneuern, widerrufen.

7 Minuten LesezeitAPIStand: 25.10.2026

Auf dieser Seite

Bevor Sie loslegen

Für wen
Wer ein Programm baut, das auf fremden Rechnern läuft und kein Geheimnis verbergen kann: ein Werkzeug für die Kommandozeile, eine Anwendung auf dem Schreibtisch, ein KI-Assistent.
Voraussetzung
die Basis-Adresse Ihrer Umgebung in SZENERA_API und ein Browser, in dem die einwilligende Person angemeldet ist
Ort
Kommandozeile und Browser

Nach dieser Seite lässt Ihre Anwendung einen Menschen entscheiden, statt einen Schlüssel zu verlangen: Sie registriert sich selbst, schickt die Person zur Einwilligung, tauscht den Code mit PKCE gegen ein Zugriffstoken oat_… und erneuert oder widerruft es. Das Passwort der Person sieht sie dabei nie.

Wann dieser Weg der richtige ist

Situation Wahl
Ihr eigener Server spricht mit Szenera ein API-Schlüssel ak_… — er gehört der Organisation und hängt an keinem Konto
Ihre Anwendung läuft bei fremden Kunden und soll deren Bestand sehen dieser Weg: Ein Mensch dort willigt ein, und Ihre Anwendung bekommt ein Token
Ein KI-Assistent soll in Ihrem Namen arbeiten dieser Weg, meist über den MCP-Dienst

Ein delegierter Zugang trägt immer zwei Seiten: die Anwendung, die handelt, und das Konto, in dessen Auftrag. Zur Laufzeit gilt die Schnittmenge aus beidem. Verliert die Person ein Recht, verliert Ihre Anwendung es im selben Augenblick mit.

Die Adressen

Ihre Anwendung muss genau eine Adresse fest kennen: die Wegbeschreibung. Alles Übrige steht darin, und zwar absolut. Aussteller und Endpunkte nennen künftig die Metadaten von auth.<ihre-domain>, wenn Ihre Umgebung diesen Wirt hat. Tragen Sie darum keinen Endpunkt von Hand ein, sondern lesen Sie ihn aus der Beschreibung, die Sie dort abrufen. Die Adressen an der Basis-Adresse der API bleiben bis auf Weiteres erreichbar.

Route Zweck
GET /.well-known/oauth-authorization-server Wegbeschreibung des Autorisierungs-Servers (RFC 8414)
GET /.well-known/oauth-protected-resource Wegbeschreibung der geschützten Ressource (RFC 9728)
POST /oauth/register Registrierung eines öffentlichen Clients (RFC 7591)
GET /oauth/authorize prüft die Anfrage und führt zur Einwilligungsseite
POST /oauth/token Code oder Erneuerungs-Token gegen eine Ausgabe tauschen
POST /oauth/revoke ein Token zurücknehmen (RFC 7009)
GET /v1/me/connected-apps die verbundenen Anwendungen des eigenen Kontos
DELETE /v1/me/connected-apps/{clientId} einer Anwendung alles nehmen, was dieses Konto ihr gab

Die ersten sechs Adressen tragen kein /v1: Ihre Pfade schreiben die Standards wörtlich vor, und ein fremder Client sucht dort und nirgends sonst. Was hinter der Einwilligung liegt, steht regulär unter /v1 — siehe Basis-URL, /v1 und Stabilität.

Schritte

  1. Holen Sie die Wegbeschreibung. Sie nennt die Endpunkte, die unterstützten Verfahren und unter scopes_supported jedes Recht, das ein delegierter Zugang tragen kann.

    curl -sS "$SZENERA_API/.well-known/oauth-authorization-server" | jq '{issuer, authorization_endpoint, token_endpoint}'
    
  2. Registrieren Sie Ihren Client — einmalig, ohne Anmeldung, ohne Geheimnis. Es gibt nur öffentliche Clients: token_endpoint_auth_method ist immer none.

    curl -sS -X POST "$SZENERA_API/oauth/register" \
      -H "Content-Type: application/json" \
      -d '{ "client_name": "Warenwirtschaft-Brücke", "redirect_uris": ["http://127.0.0.1:8765/callback"] }'
    
    { "client_id": "oac_01KQRWJRC0OAUTHCLIENT00001", "token_endpoint_auth_method": "none", "redirect_uris": ["http://127.0.0.1:8765/callback"] }
    

    Die Registrierung ist auf 10 Aufrufe je Stunde und Absenderadresse begrenzt. Legen Sie die Kennung ab und registrieren Sie nicht bei jedem Start neu.

  3. Erzeugen Sie ein Prüfwort und seine Prüfsumme. Das Verfahren ist ausschließlich S256; plain gibt es nicht.

    VERIFIER=$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=')
    CHALLENGE=$(printf %s "$VERIFIER" | openssl dgst -binary -sha256 | openssl base64 | tr '+/' '-_' | tr -d '=')
    
  4. Schicken Sie die Person in den Browser. Sie landet auf der Einwilligungsseite des Portals und sieht dort den Namen Ihrer Anwendung, das Rücksprung-Ziel und die erbetenen Rechte — gebündelt zu Bereichen mit je einem Satz und einem Schalter.

    open "$SZENERA_API/oauth/authorize?response_type=code&client_id=oac_01KQRWJRC0OAUTHCLIENT00001&redirect_uri=http%3A%2F%2F127.0.0.1%3A8765%2Fcallback&scope=scene.read%20playlist.read&state=$(openssl rand -hex 16)&code_challenge=$CHALLENGE&code_challenge_method=S256"
    

    Prüfen Sie beim Rücksprung state gegen den gesendeten Wert, bevor Sie den Code einlösen.

  5. Tauschen Sie den Code. Der Rumpf ist formularkodiert, nicht JSON.

    curl -sS -X POST "$SZENERA_API/oauth/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d grant_type=authorization_code \
      -d code=ocd_01KQRWJRC0OAUTHCODE0000001 \
      -d redirect_uri=http://127.0.0.1:8765/callback \
      -d client_id=oac_01KQRWJRC0OAUTHCLIENT00001 \
      -d code_verifier=$VERIFIER
    
    { "access_token": "oat_…", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "ort_…", "scope": "playlist.read scene.read" }
    
  6. Arbeiten Sie damit wie mit jedem anderen Bearer:

    curl -sS "$SZENERA_API/v1/me" -H "Authorization: Bearer oat_…"
    
  7. Erneuern Sie rechtzeitig. Der Erneuerungs-Token rotiert: Nach dem Tausch ist der alte verbraucht, und die Antwort trägt einen neuen.

    curl -sS -X POST "$SZENERA_API/oauth/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d grant_type=refresh_token -d refresh_token=ort_… -d client_id=oac_01KQRWJRC0OAUTHCLIENT00001
    
  8. Geben Sie zurück, was Sie nicht mehr brauchen. Die Rücknahme antwortet immer 200, auch für einen unbekannten Wert.

    curl -sS -X POST "$SZENERA_API/oauth/revoke" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d token=ort_… -d client_id=oac_01KQRWJRC0OAUTHCLIENT00001
    

Optionen

Lebensdauern

Gegenstand Gültig
Zugriffstoken oat_… eine Stunde
Erneuerungs-Token ort_… dreißig Tage, rotiert bei jedem Tausch
Autorisierungs-Code ocd_… zwei Minuten, genau eine Einlösung
offene Einwilligungs-Anfrage zehn Minuten

Rechte

Es gibt keinen eigenen Katalog: Ein Scope ist ein Rechte-Schlüssel, denselben, den auch ein API-Schlüssel tragen darf — scene.read, playlist.write und so fort. Die vollständige Liste steht als scopes_supported in beiden Wegbeschreibungen; welche Rechte für Maschinen freigegeben sind, sagt auch GET /v1/permission-catalog über das Feld appliesTo.

Beim Einwilligen greifen zwei Schnitte: Ein Recht, das Maschinen nie tragen, ist nicht erteilbar; ein Recht, das die einwilligende Person selbst nicht hält, ebenfalls nicht. Beides steht mit seinem Grund in seinem Bereich. Erbitten Sie deshalb nur, was Sie wirklich brauchen: Ein zu breiter Wunsch macht die Entscheidung schwerer und wird abgewiesen, statt stillschweigend gekürzt zu werden.

Bereiche und teilweise Einwilligung

Die Einwilligungsseite zeigt die Rechte nicht als Liste, sondern gebündelt nach der Kategorie des Rechte-Katalogs — „Szenen“, „Playlisten und Zeitpläne“, „Medien“, „Displays und Standorte“, „Berichte“. Jeder Bereich trägt einen Satz, was Ihre Anwendung darin tun kann, einen Schalter und aufklappbar die einzelnen Rechte. Alle angefragten Bereiche sind zu Beginn eingeschaltet; dieselbe Bündelung steht später in der Karte Verbundene Anwendungen, eingeklappt als Bilanz („5 Bereiche, 18 Rechte“).

Rechnen Sie mit einer Teilmenge. Der Mensch darf einzelne Bereiche abschalten, und POST /v1/oauth/authorizations/{id}/approve nimmt jede Teilmenge des Erbetenen an. Das Zugriffstoken trägt dann nur die erteilten Rechte, und die Token-Antwort nennt sie unter scope:

{ "access_token": "oat_…", "scope": "scene.read", "expires_in": 3600 }

Vergleichen Sie scope mit dem, worum Sie gebeten haben, statt es vorauszusetzen. Was fehlt, beantwortet die Plattform beim Aufruf mit 403 — nicht beim Tausch. Brauchen Sie einen Bereich wirklich, sagen Sie es der Person im Klartext und schicken Sie sie ein zweites Mal durch den Rundlauf; einen Weg, eine bestehende Einwilligung nachträglich zu erweitern, gibt es bewusst nicht.

Grenzen

GET /oauth/authorize, POST /oauth/token und POST /oauth/revoke sind auf 60 Aufrufe je Minute und Absenderadresse begrenzt, die beiden Wegbeschreibungen auf 120, die Registrierung auf 10 je Stunde. Der Echtzeit-Kanal bleibt einem delegierten Zugang verschlossen; Ereignisse holen Sie über Webhooks.

Der Betreiber der Plattform kann einen Client sperren. Dann beginnt kein neuer Rundlauf mehr, und eine laufende Erneuerung scheitert; bestehende Zugriffstoken laufen aus, statt zurückgenommen zu werden. Ebenso kann eine Organisation den delegierten Zugang ganz abschalten: Die Einwilligung scheitert dann mit OAuthAuthorization.DelegationDisabled — dort, wo der Mensch entscheidet, und nicht erst beim Tausch.

Ergebnis prüfen

  • GET /v1/me mit dem Token antwortet 200 und nennt das Konto und die Organisation, in deren Auftrag Sie handeln.
  • Die Token-Antwort nennt unter scope die tatsächlich erteilten Rechte — sie können weniger sein als die erbetenen.
  • Die Person sieht Ihre Anwendung im Portal unter Einstellungen › Mein Konto › Sicherheit in der Karte Verbundene Anwendungen, aufklappbar nach denselben Bereichen, und kann sie dort mit einem Klick widerrufen.
  • Nach einem Widerruf antwortet derselbe Aufruf 401.

Wenn etwas nicht klappt

Die Endpunkte des Standards antworten im Format des Standards ({ "error": …, "error_description": … }) und nicht im Fehlerformat dieser API. Die Routen unter /v1 antworten regulär.

Symptom Bedeutung Lösung
400 invalid_grant beim Tausch Das Prüfwort passt nicht zur Prüfsumme, oder der Code ist abgelaufen. Rundlauf neu beginnen; Prüfwort und Prüfsumme müssen aus demselben Lauf stammen.
400 invalid_grant, und alle Token sind weg Ein Code oder ein Erneuerungs-Token wurde ein zweites Mal eingelöst. Die ganze Token-Familie erlischt: Zwei Inhaber desselben Geheimnisses lassen sich nicht auseinanderhalten. Den alten Token verwerfen, neu einwilligen lassen — und nie zwei Vorgänge auf demselben Token laufen lassen.
400 ohne Weiterleitung redirect_uri steht nicht in der Liste der Registrierung. Gerade diese Adresse ist das, was nicht bestätigt werden konnte. Die Adresse bei der Registrierung eintragen und beim Tausch wortgleich mitsenden.
410 OAuthAuthorization.Expired beim Öffnen der Einwilligungsseite Die Anfrage ist älter als zehn Minuten. Ausdrücklich nicht „nicht gefunden“. Die Person erneut hinschicken.
422 mit der Nennung von Rechte-Schlüsseln Es wurde ein Scope bestätigt, den die Person nicht halten kann oder der für Anwendungen nicht vorgesehen ist. Den genannten Schlüssel aus der Anfrage nehmen.
401 mitten im Betrieb Das Zugriffstoken ist älter als eine Stunde, oder die Person hat widerrufen. Einmal erneuern; scheitert auch das, neu einwilligen lassen.

Die Codes OAuthClient.* und OAuthAuthorization.* stehen vollständig — mit Bedeutung, Auslöser und Status — unter Fehlercodes: Konten und Sitzungen; die beiden Ausweis-Codes Auth.OAuthTokenRevoked und Auth.OAuthClientBlocked unter Fehlercodes: auf jeder Route möglich.

Weiterführendes