Benutzerbereitstellung mit SCIM 2.0
fremforge implementiert SCIM 2.0 (RFC 7643/7644), damit dein IdP Forgejo-Benutzer automatisch in deiner Organisation bereitstellen kann: anlegen bei Einstellung, aktualisieren bei geänderten Attributen, deaktivieren bei Austritt. Schluss mit „John ist gerade gegangen – hat jemand daran gedacht, seinen fremforge-Zugang zu entziehen?“ Die Deaktivierung in deinem IdP setzt das SCIM-Flag active um, und fremforge deaktiviert den Forgejo-Benutzer in derselben Minute.
SCIM ergänzt OIDC, ersetzt es aber nicht. SCIM ist das Protokoll für die Bereitstellung. Es überträgt Benutzerdatensätze in fremforge. Angemeldet wird sich weiterhin über deinen separat konfigurierten Anmeldeablauf (OIDC). Die meisten kleinen Teams brauchen SCIM überhaupt nicht. Die manuelle Benutzerverwaltung in der Forgejo-Oberfläche reicht völlig. Richte SCIM erst ein, wenn „Wir haben gerade fünf Leute eingestellt – hat jemand daran gedacht, sie in fremforge anzulegen?“ zu einem echten Problem wird.
Diese Seite ist der Praxisleitfaden, um Okta / Entra / Authentik / jeden SCIM-2.0-IdP anzubinden. Plug-and-play für die großen IdPs; funktioniert mit jedem SCIM-2.0-Client.
Funktionen
| Funktion | Unterstützt |
|---|---|
POST /Users (Bereitstellen) | ✓ |
GET /Users/:id (Abfragen) | ✓ |
GET /Users (Auflisten, mit Filter userName eq) | ✓ |
PATCH /Users/:id (Operationen nach RFC 7644 §3.5.2) | ✓ |
PUT /Users/:id (vollständiges Ersetzen) | ✓ |
DELETE /Users/:id (Deaktivieren, kein endgültiges Löschen) | ✓ |
GET /ServiceProviderConfig | ✓ |
GET /ResourceTypes, GET /Schemas (Discovery) | ✓ |
POST /Groups / GET /Groups / GET /Groups/:id | ✓ |
PATCH /Groups/:id (Mitglieder hinzufügen/entfernen) | ✓ |
PUT /Groups/:id (vollständiges Ersetzen) | ✓ |
DELETE /Groups/:id (Forgejo-Team löschen + Zuordnung weich löschen) | ✓ |
Gruppenfilter displayName eq | ✓ |
| Bulk-Endpunkte | ✗ Noch nicht |
Filteroperatoren außer eq | ✗ Nutze mehrere Anfragen |
| Verschachtelte Gruppen | ✗ Forgejo bildet sie nicht ab |
Einrichtung
Schritt 1: SCIM in fremforge einschalten
- Organisationsverwaltung → SSO → SCIM-2.0-Benutzerbereitstellung → klicke auf SCIM aktivieren und Token erzeugen.
- Die Seite, die auf den Klick antwortet, zeigt das Bearer-Token einmal an. Kopiere es; du brauchst es für deinen IdP. Das Token steht nie in einer URL, und fremforge zeigt es nicht noch einmal an: Gespeichert wird nur sein SHA-256-Hash. Verlierst du es, klicke auf Token rotieren, um ein neues zu erzeugen.
- Notiere dir die auf der Seite angezeigte Basis-URL; sie sieht so aus:
https://frem.sh/<your-org>/scim/v2
Schritt 2: Deinen IdP verbinden
Okta
- Applications → Create App Integration → SCIM 2.0 Test App (Header Auth).
- Tab Provisioning → Configure API Integration:
- Base URL:
https://frem.sh/<your-org>/scim/v2 - Authentication Mode: HTTP Header
- HTTP Header Name:
Authorization - HTTP Header Value:
Bearer <token from step 1>
- Base URL:
- Test API Credentials sollte Erfolg melden.
- Tab To App → schalte Create, Update und Deactivate ein.
- Weise der App Benutzer zu. Okta sendet sie per POST an fremforge.
Microsoft Entra (Azure AD)
- Enterprise Applications → New application → Non-gallery → Name „fremforge“.
- Provisioning → Get started → Modus = Automatic:
- Tenant URL:
https://frem.sh/<your-org>/scim/v2 - Secret Token:
<token from step 1>(ohne das PräfixBearereinfügen; Entra ergänzt es)
- Tenant URL:
- Test Connection → grüner Haken.
- Mappings → nutze die Standardzuordnung für User; das einzige Feld, das oft angepasst werden muss, ist
userName: Setze es aufuserPrincipalName(die Anmeldung des Benutzers in E-Mail-Form). - Save & Start provisioning.
Authentik
- Applications → Providers → Create → SCIM Provider:
- URL:
https://frem.sh/<your-org>/scim/v2 - Token:
<token from step 1>
- URL:
- Binde den Provider an deine Application und weise eine Gruppe zu; die Benutzer in dieser Gruppe werden bereitgestellt.
Generischer SCIM-2.0-IdP
Jeder Client, der die übliche Form Authorization: Bearer <token> gegen eine SCIM-2.0-Basis-URL unterstützt, funktioniert. fremforge veröffentlicht seine Fähigkeiten unter:
GET /<your-org>/scim/v2/ServiceProviderConfig- Prüfe diese Antwort, um vor der Integration zu sehen, was unterstützt wird.
Was bei der Bereitstellung passiert
Wenn dein IdP einen Benutzer per POST sendet:
- fremforge legt einen Forgejo-Benutzer an (der Benutzername wird aus dem SCIM-
userNameabgeleitet; Namen in E-Mail-Form werden an Forgejos Regeln[a-z0-9-]angepasst, z. B.alice@acme.example→alice-acme-example). - Der Benutzer wird dem Standardteam
Membersder Organisation hinzugefügt. Er wird NICHT zum Owner befördert. Die Beförderung zum Admin bleibt bei den Operatoren. - Der Benutzer meldet sich über deine bestehende OIDC-Auth-Quelle an (separat auf der SSO-Seite eingerichtet). SCIM legt den Benutzerdatensatz an; der Anmeldeablauf auf IdP-Seite meldet ihn an.
- fremforge schreibt eine Zeile in
audit_eventsmit der Aktionscim.user.create. Sichtbar im Verwaltungs-Tab Audit-Log.
Wenn dein IdP einen Benutzer deaktiviert (PATCH active=false oder DELETE):
- fremforge setzt
prohibit_login=truebeim Forgejo-Benutzer. Sitzungen werden widerrufen und künftige Anmeldungen abgewiesen. - Die SSH-Schlüssel des Benutzers bleiben in Forgejo (sie können nicht zum Pushen genutzt werden, weil der Benutzer gesperrt ist).
- Die Mitgliedschaft in der Organisation wird für den Audit-Trail beibehalten. Um sie endgültig zu entfernen, klickt ein Admin der Organisation in der Forgejo-Oberfläche auf Remove from org.
Gruppenbereitstellung
Wenn dein IdP eine SCIM-Gruppe anlegt, macht fremforge Folgendes:
- Es legt ein Forgejo-Team in deiner Mandanten-Organisation an. Der Teamname wird aus dem
displayNameder Gruppe abgeleitet (an Forgejos Regeln[a-z0-9_-]angepasst, höchstens 30 Zeichen). - Es hält die Zuordnung in
scim_groupsfest, damit spätere PATCH-/PUT-/DELETE-Operationen wieder auf dasselbe Forgejo-Team aufgelöst werden. - Es erlaubt PATCH-Operationen auf
membersmitop=add/op=remove(RFC 7644 §3.5.2 + Kurzformmembers[value eq "<id>"]). DELETE /Groups/:idlöscht das zugrunde liegende Forgejo-Team. Die DB-Zeile wird weich gelöscht (deleted_at), damit die Zuordnung externalId↔Team ein erneutes Anlegen derselben IdP-Gruppe übersteht.
Jedes Forgejo-Team gewährt seinen Mitgliedern standardmäßig Schreibzugriff auf alle Repositorys der Organisation (eine Gruppe „Backend“ hat also Schreibzugriff auf jedes Repository). Feinerer Zugriff pro Repository wird von Operatoren in den Forgejo-Teameinstellungen konfiguriert; fremforge-SCIM überträgt keine repository-bezogenen Berechtigungen, da SCIM 2.0 keinen Standard für Attribute zu Repository-Berechtigungen hat.
Einschränkungen zum Start:
- Die E-Mail ist der Benutzerschlüssel. SCIM identifiziert Benutzer über
externalId, die wir als primäre E-Mail-Adresse des Benutzers erwarten. Das passt zu unserer bestehenden OIDC-Einstellungusername_claim. - Keine verschachtelten Gruppen. Forgejos Teammodell ist flach (ein Benutzer ist in einem Team oder nicht). Verschachtelte Gruppenhierarchien aus deinem IdP werden abgeflacht: Ein Benutzer in
Engineering → Backend → APIwird Mitglied aller drei entsprechenden Forgejo-Teams.
Token-Rotation
SCIM-Bearer-Tokens sollten regelmäßig rotiert werden. fremforge unterstützt eine Rotation ohne Ausfallzeit mit einem Fenster aus zwei Tokens:
- Organisationsverwaltung → SSO → SCIM → klicke auf Token rotieren.
- Das neue Token wird einmal auf der Seite angezeigt, die auf den Klick antwortet (nie in einer URL); kopiere es.
- Das vorherige Token bleibt gültig, bis du auf Vorheriges Token verwerfen klickst. In diesem Fenster kann dein IdP auf das neue Token wechseln, ohne laufende Bereitstellungsaufrufe zu verlieren.
- Trage das neue Token in deinem IdP ein.
- Hast du bestätigt, dass das neue Token funktioniert (prüfe einige Zyklen lang den Bereitstellungsstatus im IdP), klicke auf Vorheriges Token verwerfen.
Empfohlener Rhythmus: alle 90 Tage oder bei Personaländerungen, die eine Rotation von Zugangsdaten erfordern.
SCIM ausschalten
Organisationsverwaltung → SSO → SCIM → klicke auf SCIM deaktivieren. fremforge:
- Löscht die Hashes des aktuellen und des vorherigen Tokens (jede ausstehende IdP-Anfrage bekommt 401)
- Markiert die Zeile mit
enabled=false(im Audit sichtbar) - Lässt die Zeilen in
scim_usersunverändert (erneutes Einschalten stellt aus deinem IdP wieder bereit)
Die Forgejo-Benutzer selbst werden NICHT deaktiviert. Willst du sie alle aussperren, tu das zuerst in deinem IdP und schalte dann SCIM aus.
Fehlerbehebung
„Authorization: Bearer required“ (401) bei jeder Anfrage
Das Bearer-Token kommt nicht bei fremforge an. Häufige Ursachen:
- Falscher Header-Name: Er muss genau
Authorizationlauten. - Fehlendes Präfix
Bearer: Okta ergänzt es automatisch, manche Clients nicht. Prüfe mit tcpdump oder den ausführlichen Logs des IdP, was dein IdP tatsächlich sendet. - Token widerrufen: Hast du rotiert und das vorherige verworfen, ist das alte Token ungültig. Füge das aktuelle erneut ein.
„userName is required“ (400) bei POST
Dein IdP ordnet userName keinen sinnvollen Wert zu. In Entra heißt das oft, dass der UPN des Benutzers nicht gesetzt ist; ordne userName dann mail oder einem ähnlichen, nicht leeren Attribut zu.
Benutzer sind bereitgestellt, können sich aber nicht anmelden
SCIM legt nur den Benutzerdatensatz an. Der Anmeldeablauf nutzt deine separat konfigurierte OIDC-Auth-Quelle. Prüfe:
- Für den Benutzer ist unter Organisationsverwaltung → SSO → Auth-Quellen eine OIDC-Auth-Quelle eingerichtet.
- Die Identität des Benutzers auf IdP-Seite (E-Mail, Principal Name) stimmt mit dem
userNameüberein, den du per SCIM bereitgestellt hast. - Die Anmeldeseite unter
frem.sh/user/login?redirect_to=/<your-org>zeigt die SSO-Schaltfläche.
Der Filter funktioniert nicht für email eq oder andere Operatoren
Wir unterstützen nur userName eq "<value>". Alles andere liefert eine leere Liste. Die meisten IdPs brauchen nur userName eq zur Deduplizierung; prüfe in ihren Bereitstellungslogs, welche Filterformen sie senden, und sag uns Bescheid, wenn du weitere Operatoren brauchst (an support@frem.sh).
Audit-Trail
Jede durch SCIM ausgelöste Aktion wird im Audit-Log der Organisation mit actor=system erfasst (denn der Akteur ist „dein IdP“, kein angemeldeter Benutzer) und mit einer dieser Aktionen:
scim.enabled/scim.disabled: Aktionen in der Operator-Oberflächescim.token.rotated/scim.token.previous-dropped: Aktionen in der Operator-Oberflächescim.user.create: POST des IdPscim.user.update/scim.user.replace: PATCH/PUT des IdPscim.user.deactivate/scim.user.reactivate: Änderung des active-Flags durch den IdPscim.group.create/scim.group.update/scim.group.replace/scim.group.delete: Gruppen-Lebenszyklus im IdP- dieselben Aktionen landen im Audit-Teil des Datenexport-Bundles
Querverweise
- Organisationsverwaltung → SSO, wo du SCIM einschaltest und verwaltest
- OIDC-SSO, der Anmeldeablauf auf IdP-Seite, der mit der SCIM-Bereitstellung zusammenspielt
- Audit-Log, jedes SCIM-Ereignis in derselben Oberfläche
- Öffentliche REST-API, das programmatische Gegenstück, wenn du deinen eigenen Konnektor baust