OIDC-Single-Sign-on
fremforge unterstützt OpenID Connect (OIDC) für Single Sign-on. OIDC ist das Single-Sign-on-Protokoll, das fremforge unterstützt. Alle großen IdPs (Entra, Okta, Google Workspace, Auth0, Authentik, Keycloak) bringen OIDC von Haus aus mit. Der Lebenszyklus der Signaturschlüssel läuft automatisch über die OIDC-Discovery- und JWKS-Endpunkte.
OIDC ist derzeit das einzige Single-Sign-on-Protokoll, das fremforge anbietet. SAML ist noch nicht verfügbar; Microsoft Entra ID und ADFS unterstützen beide OIDC.
Einrichtung
Schritt 1: eine Domain verifizieren
Organisationsverwaltung → SSO → Verifizierte Domains (den eingeklappten Abschnitt aufklappen) → füge deine E-Mail-Domain hinzu (z. B. acme.com). Weise die Kontrolle über die Domain auf einem dieser Wege nach:
- DNS-TXT-Eintrag: Füge
_fremforge-verification=<token>im DNS deiner Domain hinzu und klicke dann auf Verify. - HTTP-Datei: Stelle das Token unter
https://acme.com/.well-known/fremforge-verificationbereit und klicke dann auf Verify.
Die Domain-Verifizierung ist Voraussetzung, bevor du eine Auth-Quelle registrieren kannst. Du erledigst sie nur einmal.
Schritt 2: eine OAuth-2.0-Anwendung in deinem IdP anlegen
fremforge braucht drei Werte von deinem IdP: Client ID, Client Secret und die Aussteller-URL (auch Wurzel der OIDC-Discovery-URL genannt). Konfiguriere deinen IdP wie folgt.
Okta
- Applications → Create App Integration → OIDC, Web Application.
- Sign-in redirect URIs:
https://frem.sh/user/oauth2/<auth-source-name>/callback - Sign-out redirect URIs:
https://frem.sh/<your-org>/logout(optional, aber empfohlen) - Assignments: Weise die Anwendung den Gruppen oder Nutzern zu, die Zugriff auf fremforge haben sollen.
- Kopiere Client ID, Client Secret und die Okta domain (z. B.
https://acme.okta.com).- Aussteller-URL =
https://acme.okta.com(oderhttps://acme.okta.com/oauth2/defaultbei eigenen Autorisierungsservern)
- Aussteller-URL =
Microsoft Entra (Azure AD)
- App registrations → New registration, Name „fremforge“, unterstützte Kontotypen = Single-Tenant.
- Redirect URI: Web →
https://frem.sh/user/oauth2/<auth-source-name>/callback - Certificates & secrets → New client secret, kopiere den Value sofort (er wird nur einmal angezeigt).
- Overview: Kopiere die Application (client) ID und die Directory (tenant) ID.
- Aussteller-URL =
https://login.microsoftonline.com/<tenant-id>/v2.0
- Aussteller-URL =
- Token configuration → Add groups claim, wähle Security groups. Damit wird der
groups-Claim befüllt, den fremforge für die Zuordnung zu Teams nutzt. - API permissions: Prüfe, dass
openid,profileundemailgewährt sind (standardmäßig der Fall).
ADFS
ADFS ab Windows Server 2016 ist ein OpenID-Connect-Anbieter.
- AD FS Management → Application Groups → Add Application Group, Name „fremforge“, Vorlage Server application (unter Standalone applications) oder Server application accessing a web API.
- Kopiere den Client Identifier. Redirect URI:
https://frem.sh/user/oauth2/<auth-source-name>/callback. - Configure Application Credentials → Generate a shared secret, kopiere es (es wird nur einmal angezeigt).
- Gewähre die Scopes
openid,profileundemailund füge Ausstellungs-Transformationsregeln hinzu, dieemailundname(und einen Gruppen-Claim, falls du Teams zuordnest) in das ID-Token schreiben.- Aussteller-URL =
https://<your-adfs-host>/adfs(Discovery unterhttps://<your-adfs-host>/adfs/.well-known/openid-configuration)
- Aussteller-URL =
Die OIDC-MFA-Prüfung wurde noch nicht mit ADFS getestet. Schalte sie zuerst für einen einzelnen Testnutzer ein und prüfe, ob die Anmeldung gelingt.
Google Workspace
- Google Cloud Console → APIs & Services → Credentials → Create credentials → OAuth client ID.
- Anwendungstyp: Web application.
- Authorised redirect URIs:
https://frem.sh/user/oauth2/<auth-source-name>/callback - Kopiere Client ID und Client Secret.
- Aussteller-URL =
https://accounts.google.com
- Aussteller-URL =
- Beschränke unter Google Workspace Admin → Security → API controls → Domain-wide delegation die OAuth-Einwilligung auf deine Domain, damit sich nur Mitglieder deines Workspace authentifizieren können.
Authentik
- Applications → Providers → Create → OAuth2/OpenID Connect Provider.
- Redirect URIs:
https://frem.sh/user/oauth2/<auth-source-name>/callback - Signing Key: Wähle dein Authentik-Signaturzertifikat.
- Kopiere Client ID, Client Secret und die OpenID Configuration URL (entferne
/.well-known/openid-configuration; die Aussteller-URL ist die Wurzel, z. B.https://sso.acme.internal/application/o/<slug>/). - Lege eine Application an und verknüpfe sie mit dem Provider; setze die Launch-URL auf
frem.sh/user/login?redirect_to=/<your-org>.
Keycloak
- Your Realm → Clients → Create client.
- Client type: OpenID Connect. Client ID:
fremforge. - Valid redirect URIs:
https://frem.sh/user/oauth2/<auth-source-name>/callback - Reiter Credentials: Kopiere das Client Secret.
- Aussteller-URL =
https://keycloak.acme.internal/realms/<your-realm>
- Aussteller-URL =
Auth0 / Okta Customer Identity Cloud
- Applications → Create Application → Regular Web Application.
- Allowed Callback URLs:
https://frem.sh/user/oauth2/<auth-source-name>/callback - Allowed Logout URLs:
https://frem.sh/<your-org>/logout - Settings: Kopiere Domain, Client ID und Client Secret.
- Aussteller-URL =
https://<your-auth0-domain>/
- Aussteller-URL =
Schritt 3: den Anbieter in fremforge registrieren
- Organisationsverwaltung → SSO, scrolle zu Neue SSO-Quelle hinzufügen und klicke auf Start wizard (öffnet
/_admin/sso/wizard/start). - Wähle OpenID Connect als Quelltyp und fahre fort.
- Fülle aus:
- Anzeigename: Er erscheint auf der Schaltfläche der Anmeldeseite, z. B. „Mit Okta anmelden“.
- Client ID und Client Secret aus Schritt 2.
- Aussteller-URL: fremforge ruft
<issuer>/.well-known/openid-configurationab und ermittelt die Endpunkte automatisch.
- Attribute mapping (für die meisten IdPs reichen die optionalen Standardwerte):
- Claim
email→ E-Mail in fremforge (Standard:email) - Claim
username→ Forgejo-Benutzername (Standard:preferred_username→ ersatzweiseemail) - Claim
display_name→ vollständiger Name (Standard:name)
- Claim
- Gehe die Prüf- und Bestätigungsschritte des Assistenten durch. fremforge führt einen Discovery-Abruf aus und prüft die Verbindung, bevor gespeichert wird.
Nach dem Speichern erscheint auf der Anmeldeseite deiner Organisation unter frem.sh/user/login?redirect_to=/<your-org> eine Schaltfläche Anmelden mit <name>.
Über die REST-API
Die OIDC-Auth-Quelle lässt sich auch programmatisch registrieren – nützlich, wenn du die Bereitstellung von Organisationen skriptest oder die Einrichtung aus CI steuerst. Dabei läuft dieselbe Funktion provisionOidcAuthSource wie im Admin-Assistenten.
- Zuerst eine Domain verifizieren
POST /_app/api/v1/orgs/:slug/sso/domainsmit dem Body{ "domain": "acme.com" }, danachPOST /_app/api/v1/orgs/:slug/sso/domains/:id/verify - Die OIDC-Quelle registrieren
POST /_app/api/v1/orgs/:slug/sso, der Body enthälttype: "oidc",issuer_url,client_id,client_secret - Zuordnung Gruppe→Team aktualisieren
PUT /_app/api/v1/orgs/:slug/ssomit dem Body{ "id": "...", "group_team_map": { ... } } - Quellen auflisten
GET /_app/api/v1/orgs/:slug/sso
Erfordert ein Personal Access Token (PAT) mit dem Scope sso:write:
curl -X POST \
-H "Authorization: Bearer ${FREMFORGE_PAT}" \
-H "Content-Type: application/json" \
-d '{
"name": "acme-okta",
"type": "oidc",
"issuer_url": "https://acme.okta.com",
"client_id": "0oa1abc...",
"client_secret": "s3cr3t..."
}' \
https://frem.sh/_app/api/v1/orgs/acme/ssoDie vollständige OpenAPI-Spezifikation findest du in der Referenz der öffentlichen REST-API.
Was bei der Anmeldung passiert
- Die Person klickt unter
frem.sh/user/login?redirect_to=/<your-org>auf Anmelden mit <name>. - fremforge leitet mit
scope=openid email profilezum Autorisierungsendpunkt deines IdP weiter. - Die Person authentifiziert sich beim IdP (MFA erzwingt der IdP, nicht fremforge).
- Der IdP leitet mit einem Autorisierungscode zurück nach
frem.sh/user/oauth2/<auth-source-name>/callback. - fremforge tauscht den Code gegen Tokens, prüft die Signatur des ID-Tokens gegen das JWKS des IdP, liest die Claims für E-Mail und Benutzername aus und legt den Forgejo-Benutzer an oder aktualisiert ihn.
- Ist Require SSO aktiviert (Organisationsverwaltung → SSO → Richtlinien), ist die direkte Anmeldung mit Passwort gesperrt. Nur der Weg über den IdP funktioniert.
SSO erzwingen
Organisationsverwaltung → SSO → Richtlinien → Require SSO for all members. Nach dem Aktivieren gilt:
- Bestehende Mitglieder müssen sich bei der nächsten Anmeldung über den IdP neu authentifizieren.
- PATs und SSH-Schlüssel bleiben als Authentifizierungsmittel gültig, aber mit aktiviertem Require SSO wird die IdP-Sitzung bei Git-Operationen alle 15 Minuten neu geprüft. Wer im IdP deaktiviert wird, verliert daher innerhalb von 15 Minuten den Push-/Pull-Zugriff, auch wenn sein SSH-Schlüssel noch registriert ist. Ein separates Widerrufen der Schlüssel ist nicht nötig.
- Neue Einladungen von Mitgliedern führen zu reinen SSO-Konten.
Mit SCIM für den vollständigen Lebenszyklus kombinieren
OIDC übernimmt die Authentifizierung. Um die Bereitstellung und Deprovisionierung von Nutzern zu automatisieren (Konten bei Einstellung anlegen, bei Austritt deaktivieren, Gruppenmitgliedschaften synchronisieren), kombiniere OIDC mit der SCIM-2.0-Bereitstellung.
Die meisten Unternehmens-IdPs (Okta, Entra) unterstützen OIDC und SCIM gleichzeitig. Die typische Einrichtung:
- OIDC konfigurieren, damit sich Mitglieder über den IdP anmelden können.
- SCIM aktivieren, damit der IdP Änderungen an Nutzern und Gruppen automatisch überträgt.
- Require SSO aktivieren. Mit aktivem SCIM sperrt die Deprovisionierung im IdP den Zugriff auf fremforge sofort.
Rotation der Schlüssel
fremforge speichert das JWKS (die Signaturschlüssel) des IdP zwischen und aktualisiert es nach Zeitplan sowie bei einer fehlgeschlagenen Signaturprüfung. Eine Schlüsselrotation auf IdP-Seite (z. B. die automatische Schlüsselrotation von Okta) wird transparent verarbeitet. Du musst nichts tun.
Wenn du das Client Secret im IdP rotierst:
Die Karte der Auth-Quelle unter Organisationsverwaltung → SSO hat kein Feld für das Client Secret, und eine Auth-Quelle lässt sich nach dem Anlegen nicht mehr bearbeiten. Um das Secret zu ändern, wende dich an support@frem.sh, bevor du das alte im IdP widerrufst: Wir aktualisieren es für dich, und die Anmeldung funktioniert weiter.
OIDC deaktivieren
Um die Anmeldung über OIDC zu beenden, entferne die Auth-Quelle: Organisationsverwaltung → SSO → <Auth-Quelle> → Entfernen. Die Anmeldung darüber endet sofort. Hat sich noch kein Mitglied darüber angemeldet, wird sie gelöscht; andernfalls behält fremforge eine abgeschaltete, umbenannte Kopie, damit die Konten erhalten bleiben. Konten, Sitzungen und Zugriffstoken dieser Mitglieder werden nicht widerrufen: Um diesen Zugriff zu beenden, entferne die Mitglieder aus der Organisation oder deprovisioniere sie über SCIM. Wer nur den OIDC-Weg hatte, fällt auf E-Mail und Passwort zurück (wenn ein lokales Passwort gesetzt ist) oder kann sich nicht mehr anmelden; stelle also vorher sicher, dass sich ein Break-Glass-Owner noch mit einem lokalen Passwort anmelden kann. Schlägt das Entfernen fehl, sagt die Konsole das, es ändert sich nichts und die Anmeldung über die Quelle funktioniert weiter.
Es gibt keinen Schalter, der eine Auth-Quelle vorübergehend ab- und später wieder einschaltet; wende dich dafür an support@frem.sh. Damit keine verwaisten Konten entstehen, entferne die Auth-Quelle, bevor du die Anwendung in deinem IdP abbaust, nicht danach.
Fehlerbehebung
Redirect-URI stimmt nicht überein
Der IdP lehnt den Callback ab, wenn die im IdP registrierte Redirect-URI nicht exakt https://frem.sh/user/oauth2/<auth-source-name>/callback entspricht. <auth-source-name> ist der Name, den du beim Hinzufügen der Auth-Quelle in fremforge vergeben hast (z. B. okta-primary, entra-prod); der OAuth2-Router von Forgejo verteilt den Callback anhand dieses Namens. Kopiere die exakte Callback-URL aus dem Feld Redirect URI, das der SSO-Assistent beim Hinzufügen der Auth-Quelle anzeigt (Organisationsverwaltung → SSO → + SSO-Quelle hinzufügen), statt sie abzutippen; bei der URL zählen Groß- und Kleinschreibung und abschließende Schrägstriche.
invalid_client beim Token-Austausch
Client ID oder Client Secret ist falsch. Kopiere sie erneut aus der IdP-Konsole. Manche IdPs zeigen das Secret nur einmal beim Anlegen an. Erzeuge ein neues Secret, wenn du das ursprüngliche nicht gesichert hast.
Claims fehlen (Benutzername oder E-Mail leer)
Prüfe die Richtlinie deines IdP für die Freigabe von Attributen und Claims. fremforge benötigt mindestens den Claim email im ID-Token. Wenn dein IdP die Freigabe von Claims an ausdrückliche Berechtigungen knüpft (Entra verlangt z. B. die API-Berechtigungen profile und email), stelle sicher, dass sie gewährt und bestätigt sind.
Nutzer bereitgestellt, aber Anmeldung schlägt fehl
Ist Require SSO aktiviert und passt die E-Mail-Domain der Person zu keiner verifizierten Domain, blockiert fremforge die Anmeldung. Verifiziere die Domain unter Organisationsverwaltung → SSO → Verifizierte Domains. Die Domain im Claim email der Person muss übereinstimmen.
Step-up mit Sitzungsbindung pro Organisation
Über die normale SSO-Anmeldung hinaus kann fremforge jedes Mal eine frische, vom IdP bestätigte Authentifizierung erzwingen, wenn jemand in den Verwaltungsbereich einer anderen Organisation wechselt. Das ist die auf der Preisseite zugesagte „Sitzungsbindung pro Organisation“ in der Stärke für regulierte Branchen – nützlich, wenn jede organisationsübergreifende Verwaltungsaktion eine vom IdP bestätigte Authentifizierung für genau diese Organisation tragen muss.
Es gibt zwei Stärkestufen. Die Bindung ist standardmäßig aktiv; welche Stufe gilt, hängt davon ab, ob du den unten beschriebenen Step-up-Client einrichtest:
- Weiche Bindung (Standard, wenn du keinen Step-up einrichtest): Die Umleitung beim ersten Zugriff auf eine andere Organisation läuft über Forgejos universelles
/user/login. Ist deine Forgejo-Sitzung aktuell, ist der Umweg unsichtbar und fragt nichts ab. Er beweist also, dass der Browser eine gültige Sitzung hat, nicht, dass sich die Person erneut authentifiziert hat. Nutze die harte Bindung, wenn du pro Organisation eine frische Authentifizierung brauchst. Der Break-Glass-Zugang mit lokalen Anmeldedaten bleibt erhalten. - Harte Bindung (siehe Einrichtung unten): Die Umleitung läuft über den Step-up-Endpunkt von fremforge, der bei deinem IdP eine OIDC-Authentifizierung mit
prompt=loginstartet. Der IdP MUSS erneut nach Anmeldedaten und MFA fragen; wir prüfen, dassauth_timeim zurückgegebenen ID-Token höchstens 5 Minuten alt ist. Der Break-Glass-Zugang mit lokalen Anmeldedaten über/user/loginfunktioniert für Owner der Organisation weiterhin; die harte Bindung ändert nur den Weg beim organisationsübergreifenden Zugriff, nicht die universelle Anmeldung.
Harte Bindung einrichten
Die harte Bindung erfordert einen ZWEITEN OIDC-Client in deinem IdP neben dem, den Forgejo nutzt (gleicher Aussteller, eigene client_id und eigenes client_secret, eigene Redirect-URI).
Registriere in deinem IdP eine neue OIDC-Anwendung:
Feld Wert Anwendungstyp Web (vertraulich) Grant-Typen Authorization Code, mit PKCE Redirect-URI https://frem.sh/<your-org>/_admin/-/stepup/callbackAuthentifizierungsmethode am Token-Endpunkt client_secret_basicoderclient_secret_postErforderliche Scopes openid,emailClaim auth_timeIm ID-Token erforderlich prompt=loginWird beachtet (Standardverhalten der meisten IdPs) Gehe in fremforge zu Organisationsverwaltung → SSO, klappe Add OIDC auth source auf und fülle unten im Formular die optionalen Felder unter Per-org session-binding step-up aus:
- Step-up Client ID: aus der neuen App in deinem IdP
- Step-up Client Secret: aus der neuen App in deinem IdP; wird vor dem Speichern mit AES-256-GCM (Unterschlüssel per HKDF abgeleitet) verschlüsselt abgelegt
- Step-up Redirect URI:
https://frem.sh/<your-org>/_admin/-/stepup/callback
Prüfen: Öffne
https://frem.sh/<your-org>/_admin/billingin einem neuen Browserfenster. Du solltest über deinen IdP umgeleitet werden, erneut zur Anmeldung aufgefordert werden und wieder auf der Abrechnungsseite landen. Das Audit-Log zeigt ein Ereignisorg-session.step-up.okmitauth_time.
Bleiben die Step-up-Felder leer, fällt die Auth-Quelle auf die weiche Bindung zurück – nützlich für Organisationen, die SSO bei der Anmeldung wollen, aber keine IdP-Bestätigung pro Organisation brauchen.
Fehlerbehebung bei der harten Bindung
- „IdP did not emit auth_time“: Der IdP hat ein ID-Token ohne den Claim
auth_timezurückgegeben. fremforge braucht ihn, weil wir daran prüfen, wie frisch die erneute Authentifizierung ist. Prüfe die Claim-Richtlinie des IdP; die meisten haben eine Option wie „include auth_time“. - „auth_time too old“: Der IdP hat
prompt=loginauf Protokollebene akzeptiert, die Person aber nicht tatsächlich erneut abgefragt. Verschärfe die Richtlinie für „Session Lifetime“ oder „Max Age“ des IdP für diesen Client. - „step-up cookie binding mismatch“: Die Person hat mitten im Ablauf die Identität gewechselt (z. B. einen zweiten Browser-Tab geöffnet und sich als andere Person angemeldet). Beginne erneut bei
/<your-org>/_admin/billing. - „step-up redirect URI rejected“: Die URI hat unsere Prüfung auf öffentliches HTTPS nicht bestanden (private, Loopback- und Metadaten-Adressen sind gesperrt). Verwende die kanonische Form
frem.sh/_app.
Querverweise
- SAML: warum SAML noch nicht verfügbar ist
- SCIM-2.0-Nutzerbereitstellung: den Lebenszyklus von Nutzern über den SCIM-Client deines IdP automatisieren
- Sicherheit und Lieferkette: das Sicherheitsmodell von fremforge rund um SSO-Sitzungen
- Organisationsverwaltung: Überblick über alle Bereiche der Verwaltung