Monosign-Verwaltungs-API, SCIM 2.0 und Webhooks

Was hat sich geändert

Jede Inhaltsänderung wird versioniert. Wählen Sie eine Version, um sie mit der vorherigen zu vergleichen.

Version 7 → 8

Aktualisierung

Zwei Module ergänzt, damit der Kurs die MCIE-Prüfung abdeckt: OAuth-Clients und Token-Laufzeiten, das Lesen eines 403, Mandanten, die Endpunkte für Zuweisungen und Berechtigungen, die Aufrufe des SCIM-Push und das Lesen seiner Ergebnisse sowie Provision Services mit ihren Dead Letters. Die neuen Lektionen erhielten Diagramme und Listen für die erste Prüfung.

5 Lektionen aktualisiertDauer

Inhaltliche Aktualisierung. Eingeschriebene Lernende wurden benachrichtigt.

Dauer von 30 auf 34 Minuten geändert.

Ein Backend spricht nicht nur über einen `Rest API`-Schlüssel mit Monosign. Wenn Ihre eigene API Tokens annehmen soll, die Monosign ausstellt, ist der Aufrufer ein **OAuth-Client**, und einige Regeln entscheiden, ob seine Token-Anfrage gelingt. ### Ein Schlüssel ist ein Client Ein Client ist ein Anwendungsschlüssel vom Typ `OIDC/OpenID`, `OAuth 2.0` oder `JWT`. Der Schlüssel ist die `client_id`, das Schlüsselgeheimnis das `client_secret`. Die drei Schlüsseltypen werden unter drei Pfadpräfixen bedient: `/openid`, `/oauth` und `/jwt`. Der Handler dahinter ist derselbe, aber das Präfix bestimmt, welcher Schlüsseltyp gesucht wird. Ein Client muss deshalb das Präfix des Typs aufrufen, mit dem er angelegt wurde. Korrekte ID und korrektes Geheimnis am falschen Präfix werden abgelehnt. ### Die Client-Credentials-Anfrage Ein Backend-Job hat keinen Benutzer und keinen Browser, also nutzt er den Client-Credentials-Grant. Die Anfrage braucht nur den Grant-Typ und die eigenen Zugangsdaten des Clients: ``` POST /oauth/token Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=<Schlüssel>&client_secret=<Schlüsselgeheimnis> ``` In diesem Ablauf gibt es keine Weiterleitungsadresse und keinen Benutzernamen, weil sich niemand anmeldet. ::diagram api-client-credentials ### Public Clients können das nicht Ein Schlüssel mit aktiviertem `Public Client` ist für Single-Page-, Mobil- und Kommandozeilen-Apps gedacht. Er hat kein Geheimnis, PKCE wird Pflicht, und der Client-Credentials-Grant wird mit `The client_credentials grant is not allowed for public clients.` abgelehnt. Schalten Sie die Option nicht ab, damit ein Backend-Job läuft. Registrieren Sie für den Job einen zweiten, vertraulichen Client mit eigenem Schlüssel und Geheimnis, damit jeder Aufrufer einzeln rotiert werden kann. ### Laufzeiten gelten in Minuten | Einstellung | Leer oder `0` bedeutet | Einheit | | --- | --- | --- | | `Access Token Lifetime` | 5 Minuten | Minuten | | `Refresh Token Lifetime` | 30 Minuten | Minuten | | `ID Token Lifetime` | 1 Minute | Minuten | Bis v2026.07-hf02 las der Client-Credentials-Pfad diese Werte als Sekunden, obwohl das Formular `In minutes` anzeigte. Seit v2026.09 liest jeder Pfad Minuten. Ein Schlüssel, der im alten Build mit `3600` für eine Stunde eingestellt wurde, stellt jetzt Tokens aus, die 3600 Minuten leben, also 60 Stunden. Tragen Sie nach dem Upgrade `60` ein. ### Was in welches Token gelangt `Audience` und `Resource` am Schlüssel werden nur in das **Access Token** geschrieben. Das ID Token richtet sich an den Client selbst, daher bleibt sein `aud` die Client-ID. Eine API, die `aud` prüft, muss also Access Tokens prüfen, niemals ID Tokens. ### Das Deaktivieren eines Benutzers ruft keine Tokens zurück Bereits ausgestellte Access Tokens bleiben bis zu ihrem `exp` gültig. Gestoppt wird die nächste Erneuerung: Für einen Benutzer, der nicht aktiv oder nicht `Enabled` ist, antwortet der Token-Endpunkt mit `The refresh token is no longer valid.` Die Lücke dazwischen entspricht der Laufzeit des Access Tokens. Eine kurze `Access Token Lifetime` ist deshalb die Stellschraube, die sie verkleinert. ### Was Sie zuerst prüfen, wenn eine Token-Anfrage scheitert 1. Passt das Pfadpräfix (`/openid`, `/oauth` oder `/jwt`) zu dem Typ, mit dem der Schlüssel angelegt wurde? 2. Ist `Public Client` eingeschaltet? Ein solcher Schlüssel kann den Client Credentials Grant nicht verwenden. 3. Leben Tokens nach einem Upgrade viel länger als geplant? Lesen Sie die Lebensdauerfelder als Minuten.
Die meisten Supportfälle zu einer Integration beginnen mit einem einzigen abgelehnten Aufruf. Die Antwort selbst sagt Ihnen, was zu tun ist, wenn Sie sie vollständig lesen. ### Der 403 nennt die Berechtigung Bei aktivierter API Security antwortet ein Aufruf an einen Endpunkt, dessen Berechtigung dem Schlüssel nicht erteilt wurde, mit HTTP 403. Der Body sieht so aus: ``` { "Message": "Permission Denied", "InternalMessage": "Permission denied for this API endpoint. You need to have one of the following permission(s): System.API.Users.View." } ``` `InternalMessage` listet die Berechtigungen auf, die der Endpunkt akzeptiert. Das Vorgehen ist immer gleich: 1. Kopieren Sie den Berechtigungsnamen aus dem 403. 2. Öffnen Sie die Anwendung, `Keys`, den Schlüssel und den Tab `Permissions`. 3. Suchen Sie den Namen mit `Search` und erteilen Sie ihn mit `Grant`. Erteilen Sie genau das, was der 403 genannt hat. Eine breitere Berechtigung erweitert, was der Schlüssel aufrufen kann. ### Warum der nächste Aufruf trotzdem scheitern kann Jeder API-Prozess antwortet aus seiner eigenen Kopie der Sicherheitseinstellungen im Arbeitsspeicher. Eine Änderung wird wirksam, sobald der Prozess seinen zwischengespeicherten Eintrag verwirft. Das geschieht kurz danach, nicht sofort. Hinter einem Load Balancer können zwei Instanzen in diesem kurzen Fenster unterschiedlich antworten. Liefert ein Aufruf direkt nach dem Erteilen noch 403, warten Sie einen Moment und testen Sie eine Instanz nach der anderen. Reagieren Sie nicht mit weiteren Berechtigungen und schalten Sie API Security nicht ab. ::diagram api-403-path ### Was der Standard aus v2026.09 nicht anfasst Der sichere Standard wird nur in einem Moment geschrieben: wenn ein neuer `Rest API`-Schlüssel an einer Anwendung angelegt wird, die noch nie eine Einstellung hatte. Zwei Folgen helfen, wenn ein Kunde nach bestehenden Integrationen fragt: - Eine Anwendung mit einer ausdrücklichen Wahl, ein oder aus, behält sie. - Das Bearbeiten eines bestehenden Schlüssels wendet den Standard nie an. ### Mandanten Ein Schlüssel gehört zu einem Mandanten. Der Schlüssel eines Kundenmandanten kann nie in einem anderen Mandanten handeln. Seit v2026.10 gibt es genau eine unterstützte Übergabe: Ein Schlüssel der **Master-Anwendung `api` des Hauptmandanten** darf mit seinem Aufruf einen Übergabe-Header für den Basismandanten senden, und der Aufruf läuft dann im Mandanten der Anfrage. Jeder andere Schlüssel, der das versucht, erhält `Invalid Application Key`. Für Automatisierung über mehrere Mandanten ist die Wahl daher einfach: den eigenen Schlüssel jedes Zielmandanten verwenden oder die Master-Anwendung des Hauptmandanten. ### API-Schreibvorgänge provisionieren nicht von selbst Das Anlegen, Speichern oder Entfernen eines Benutzers in Management stellt den Benutzer immer in die Warteschlange der Provision Services. Die API verhält sich anders: Ein Anlegen oder Aktualisieren stößt die Provisionierung nur an, wenn der Aufruf `AutoProvision` setzt. Erreichen Benutzer aus einer HR-Integration den Provisionierungsendpunkt eines Kunden nie, von Hand angelegte aber schon, prüfen Sie zuerst den Request-Body und erst dann den Dienst.
Drei Ressourcenfamilien tragen den größten Teil der Lifecycle-Automatisierung: Anwendungszuweisungen, Berechtigungen (Entitlements) und Audits. Jede hat ein Verhalten, das Integratoren überrascht. ### Anwendungszuweisungen | Aufruf | Berechtigung | Was er tut | | --- | --- | --- | | `POST v1.4/application-users/detail` | `System.API.ApplicationUsers.View` | Liest eine Zuweisung | | `PUT v1.4/application-users` | `System.API.ApplicationUsers.Edit` | Ändert eine bestehende Zuweisung | | `DELETE v1.4/application-users/{id}` | `System.API.ApplicationUsers.Remove` | Entfernt eine Zuweisung (ab v2026.10) | `PUT` legt nie eine Zuweisung an. Es sucht eine aktive, nicht entfernte Zuweisung für die gesendete `UserId` und `ApplicationId` und antwortet mit 404 `Application user not found`, wenn es keine gibt. ### Ein Ablaufdatum richtig verlängern Die Anfrage hat zwei Datumsfelder mit unterschiedlichen Aufgaben. `NewExpirationDate` **schreibt** das neue Ablaufdatum. Das ältere `ExpirationDate` **grenzt nur die Suche ein**. Wer das neue Datum dort sendet, lässt die Suche die Zeile verfehlen, und der Aufruf antwortet mit 404. ``` PUT v1.4/application-users { "UserId": "<Benutzer-ID>", "ApplicationId": "<Anwendungs-ID>", "NewExpirationDate": "2026-12-31T23:59:59Z" } ``` Lassen Sie `ExpirationDate` weg. Prüfen Sie außerdem, was Ihre JSON-Bibliothek für ein nicht gesetztes Datum sendet. `NewExpirationDate` wird angewendet, sobald es einen Wert hat, und der Server schützt nicht vor Werten in der Vergangenheit: Ein Standarddatum wie `0001-01-01T00:00:00` lässt die Zuweisung sofort ablaufen. Senden Sie `null` oder lassen Sie das Feld weg, wenn Sie das Ablaufdatum nicht ändern wollen. ### Was sich mit v2026.10 geändert hat - Ein Schlüssel ohne Master-Rechte erreicht nur die Zuweisungen **seiner eigenen Anwendung**. Detail, `PUT` und `DELETE` für die Zuweisung einer anderen Anwendung antworten mit 404 `Application user not found`. Eine Integration, die mehrere Anwendungen verwaltet, braucht Master-Rechte oder einen Schlüssel je Anwendung. - `DELETE v1.4/application-users/{id}` ist neu. Es entfernt die Zuweisung weich, führt den Trigger `Removed` aus und schreibt das Entzugsereignis in die Zugriffszeitleiste. Nutzen Sie es für das Deprovisionieren. Ein Ablaufdatum in der Vergangenheit lässt die Zuweisung nur ablaufen und erzeugt diese Spur nicht. ### Gruppenmitgliedschaften über Entitlements `POST v1.5/entitlements/groups` fügt einen Benutzer einer Gruppe hinzu. Ab v2026.10 antwortet eine Wiederholung desselben Hinzufügens mit `409` und dem Code `EntitlementAlreadyExists` und enthält die ID der bestehenden Mitgliedschaft. Für einen Client, der nach einem Timeout wiederholt, macht genau diese Antwort den Aufruf idempotent: Werten Sie sie als erledigt. `DELETE v1.5/entitlements/{objectAssignmentId}` mit dieser ID beendet die Mitgliedschaft. Vor v2026.10 speicherte derselbe Aufruf einen Eintrag, den der Gruppenspeicher nie sah, sodass Regeln und Trigger die Mitgliedschaft ignorierten. Diese alten Einträge bleiben auch nach dem Upgrade ignoriert. Die Lösung ist, die Mitgliedschaften über die API erneut hinzuzufügen. ::diagram api-entitlement-retry ### Audits sind keine Listen-API `v1.4/audit` bietet `GET {id}`, `POST` und `POST bulk`. Die beiden letzten schreiben Audit-Zeilen für externe Systeme. Eine Listenroute gibt es nicht, obwohl eine Berechtigung namens `System.API.Audits.List` existiert, und die Seite Audit hat auch keinen Dateiexport. Um die Audit-Zeilen einer Woche in einen Data Lake zu bringen, erstellen Sie einen Report-Studio-Bericht auf der Datenquelle `Audit Events` und liefern ihn als Datei aus.
Ein Zielhersteller wird fragen, welche SCIM-Operationen er unterstützen muss. Die Antwort ist kurz, und wer sie kennt, versteht die meisten Symptome, die später auftreten. ### Die Aufrufe für einen Benutzer Für jeden zugewiesenen Benutzer sucht der Push den Benutzer zuerst und entscheidet dann: ``` GET /Users?filter=userName eq "jdoe" ``` | Suchergebnis | Zuweisung | Nächster Aufruf | | --- | --- | --- | | Kein Benutzer | Aktiv | `POST /Users` | | Ein Benutzer | Aktiv | `PUT /Users/{id}` | | Ein Benutzer | Inaktiv | `DELETE /Users/{id}` | | Mehr als ein Benutzer | Beliebig | Keiner, der Benutzer wird abgebrochen | Das Benutzerdokument enthält `userName`, die geschäftliche E-Mail, Vor- und Nachname, `externalId` und `active`. Der Benutzer-Push verwendet kein `PATCH`. Ein Ziel muss also den Parameter `filter` mit `eq` sowie `POST`, `PUT` und `DELETE` auf `/Users` unterstützen. ::diagram api-scim-user-decision ### Das Suchattribut wählen `User Identifier Property` in den erweiterten Einstellungen bestimmt, welches Attribut der Filter verwendet. Standard ist `externalId`. Die anderen sinnvollen Werte sind `userName` und `email`. Zwei Zeilen im Dienstprotokoll zeigen, dass die Wahl nicht zum Ziel passt: | Zeile im Dienstprotokoll | Bedeutung | Lösung | | --- | --- | --- | | `SCIM API returned no result for user ... Will be created.` bei jedem Lauf, dazu wachsende Duplikate | Das Ziel speichert das gefilterte Attribut nicht, die Suche geht immer ins Leere | Ein Attribut wählen, das das Ziel speichert, etwa `userName` oder `email` | | `SCIM API returned more than one user ...` und der Benutzer wird nie aktualisiert | Das Attribut ist am Ziel nicht eindeutig | Ein Attribut wählen, das auf genau ein Konto zeigt | ### Force Sync und der Zeitplan `Force Sync` überträgt Benutzer und Gruppen sofort, unabhängig von `Features` und `Enable Auto-sync`, und ist damit die richtige Schaltfläche während des Tests. Die Antwort lautet etwa `120 users sync is completed. [112 success / 0 skipped / 8 error]`. Lesen Sie die Zahlen sorgfältig: Der Zähler skipped wird nie erhöht, daher erscheinen übersprungene Benutzer, etwa wegen eines fehlenden Vornamens, unter error. Prüfen Sie das Dienstprotokoll, bevor Sie das Ziel verantwortlich machen. Ein **geplanter** Push startet nur, wenn drei Dinge zutreffen: Die Anwendung ist aktiviert, `Enable Auto-sync` ist an, und ein `Timing`-Eintrag hat ein nächstes Vorkommen, das bereits fällig ist. `Timing` bietet jede Stunde zu einer bestimmten Minute oder jeden Tag zu einer bestimmten Uhrzeit, beides in UTC, und das Formular zeigt daneben die aktuelle UTC- und Ortszeit. Ein Kunde mit UTC+3, der 02:00 Ortszeit möchte, trägt `Every Day at 23:00` ein. ### Gruppen Gruppen werden mit `PUT` geschrieben und über `externalId` zugeordnet, das die Monosign-Gruppen-ID enthält. Der Gruppenschritt liest die `externalId` jeder Gruppe am Ziel als eine solche ID. Eine einzige alte Zielgruppe mit einer Textbezeichnung in `externalId` stoppt den gesamten Gruppenschritt, und keine Ihrer zugeordneten Gruppen kommt an. Bereinigen Sie diese Gruppe zuerst am Ziel. `Group Identifier Property` wird gespeichert, aber vom Push nicht gelesen. Eine Änderung hilft also nicht. ### Ausgehender Proxy Der Push liest die globale Einstellung `Proxy Host` unter Settings, `System`. Laut Beschreibung wird der Proxy für SCIM-, SMS-, Anruf-, Push- und Lizenzdienste verwendet. Ist das Feld leer, verbindet sich der Push direkt. In Netzen, in denen nur der Proxy ins Internet darf, schlägt das fehl. ### Stattdessen die Gruppen einer SaaS-Anwendung lesen Die Quelle `SCIM Entitlement Provider` arbeitet in die andere Richtung: Sie importiert die Gruppen der Anwendung als Berechtigungen und deren Mitglieder als Zuweisungen. Ihr `Test` führt vier Schritte aus: `Connect to SCIM endpoint`, `Read users and groups`, `Provisioning capability` und `User matching`. Endet der dritte mit der Warnung, dass der Server keine PATCH-Unterstützung ausweist, funktioniert der Import weiterhin. Das Hinzufügen und Entfernen von Mitgliedern aus Monosign schlägt aber wahrscheinlich fehl, weil Mitgliedschaften mit `PATCH /Groups/{id}` provisioniert werden. ### Was Sie zuerst prüfen | Symptom | Wo Sie nachsehen | | --- | --- | | Duplikate oder Benutzer, die nie aktualisiert werden | `User Identifier Property` und die beiden Zeilen im Dienstprotokoll oben | | `Force Sync` meldet Fehler | Das Dienstprotokoll, denn übersprungene Benutzer zählen als Fehler | | Der geplante Push startet nie | Anwendung aktiviert, `Enable Auto-sync` an und ein `Timing`-Eintrag in UTC | | Keine zugeordnete Gruppe kommt an | Die `externalId` der Gruppen, die im Ziel bereits existieren | | Der Push kann keine Verbindung aufbauen | `Proxy Host` unter Settings, `System` |
SCIM ist nicht der einzige ausgehende Weg. Ein **Provision Service** bindet einen Provisionierungsanbieter an eine Anwendung, mit Titel, `Url`, JSON-Einstellungen und Regeln. Der Benutzerprovisionierungsdienst prüft jeden Benutzer gegen jeden aktivierten Service und sendet Provisionierungs- oder Deprovisionierungsarbeit an den Endpunkt des Kunden. Wenn Sie diesen Endpunkt bauen, bestimmt das Leben einer einzelnen Arbeitszeile Ihr Design. ### Das Leben einer Zeile | Schritt | Was geschieht | | --- | --- | | Eingereiht | Eine Zeile wartet als `WaitingForProvision` (oder das Gegenstück für die Deprovisionierung) | | Gesendet | Der Dienst sendet ein POST an die `Url`; die Zeile wird `Provisioning` | | Ihr Endpunkt antwortet mit 2xx | Sonst ändert sich nichts. Es gibt keinen Rückruf, und nichts setzt die Zeile auf provisioniert | | Etwa eine Stunde später | Ein Durchlauf setzt Zeilen, die noch unterwegs sind, zurück auf wartend, und die Zeile wird erneut gesendet | | 48 Stunden nach dem Anlegen der Zeile | Sie wird mit der Meldung, dass das Wiederholungsbudget verbraucht ist, als Fehler markiert und erscheint unter `Dead Letters` | Die Folge ist der wichtigste Satz dieser Lektion: **Ein 2xx beendet die Zeile nicht, Ihr Endpunkt erhält denselben Benutzer also etwa jede Stunde erneut.** Entwerfen Sie ihn so, dass eine Wiederholung nichts verändert: zuerst das Konto suchen, nur anlegen, wenn es fehlt, und in beiden Fällen mit 2xx antworten. ::diagram api-provision-row-life ### Drei Einstellungen, die in die Irre führen - **`Url` ist kein Pflichtfeld.** Bei leerer `Url` bleiben die Zeilen des Service für immer `WaitingForProvision`, und es wird kein Fehler protokolliert. Prüfen Sie das zuerst, wenn ein neuer Service nichts zustellt. - **`State` ist ein gespeichertes Abzeichen.** Es startet und stoppt nichts. - **`Remove` löscht nicht.** Es setzt nur `Is Enabled` auf false, und die meisten Rollen erhalten dabei 403. Um einen Service vorübergehend außer Betrieb zu nehmen, öffnen Sie ihn mit `Edit`, entfernen den Haken bei `Is Enabled` und speichern. Die Pause ist umkehrbar und deprovisioniert die Konten nicht, die der Service bereits angelegt hat. ### Wer als außerhalb des Geltungsbereichs zählt Ein Benutzer, der inaktiv ist, nicht `Enabled` ist oder **keine E-Mail-Adresse hat**, gilt als außerhalb jeder Regel und wird zur Deprovisionierung eingereiht. Eine Datenbereinigung, die E-Mail-Adressen leert, kann daher echte Konten auf Kundenseite entfernen. Stimmen Sie das vor einer solchen Bereinigung mit dem HR-Team ab. `Start Full User Provision` prüft jeden Benutzer gegen jeden aktivierten Service. Der Hinweis `Full User Provision is Started.` erscheint, bevor irgendeine Arbeit erledigt ist, und es gibt keine Fortschrittsansicht. Prüfen Sie vor dem Klick die Regeln und `Is Enabled` an jedem Service, denn Benutzer außerhalb einer Regel werden zum Entfernen eingereiht. ### Dead Letters der Provisionierung Management, System, Services, `Dead Letters` listet die Provisionierungszeilen auf, deren Budget verbraucht ist. Sie werden nicht von selbst wiederholt. | Schaltfläche | Wann verwenden | Wirkung | | --- | --- | --- | | `Requeue` | Die Ursache ist behoben und der Benutzer braucht das Konto noch | Die Zeile geht in ihren Wartezustand zurück, und der Dienst nimmt sie wieder auf. Sie kann erneut scheitern und in die Liste zurückkehren | | `Discard` | Die Arbeit ist bereits anders erledigt, etwa weil die IT das Konto von Hand angelegt hat | Die Zeile wechselt in einen endgültigen verworfenen Zustand, behält Inhalt und letzten Fehler, und es wird nichts gesendet | Ein Discard lässt sich nicht rückgängig machen, blockiert aber die Zukunft nicht: Wird der Benutzer wieder berechtigt, wird neue Arbeit eingereiht.