Organisationen und Rollen für B2B-SaaS modellieren: Teams, Berechtigungen und Einladungen richtig gemacht
Die meisten SaaS-Produkte starten mit einem einzelnen Nutzer. Du baust das Kernfeature, lieferst aus, gewinnst erste Anwender, und alles läuft gut. Bis dein erster Enterprise-Interessent fragt, wer sonst noch aus seinem Team sich anmelden kann, ob verschiedene Personen verschiedene Zugriffsstufen haben können und wie er neue Mitglieder hinzufügt, ohne bei dir anzurufen. Dann merkst du, dass das gesamte Berechtigungsmodell fehlt.
RBAC für B2B-SaaS ist kein Feature, das du aufschieben kannst. Es ist strukturell. Es falsch zu machen bedeutet, Authentifizierung umzuverdrahten, API-Guards neu zu schreiben, bestehende Daten zu migrieren und Kunden zu erklären, warum sie ein Wochenende lang keinen Zugriff hatten. Es von Anfang an richtig zu machen kostet einen Bruchteil davon.
Dieser Beitrag zeigt, wie du Organisationen, Rollen und Einladungsflüsse so entwirfst, dass dein Mehrbenutzer-Account-Modell das leistet, was Enterprise-Käufer erwarten, ohne es zu überkonstruieren, bevor du Kunden hast.
Warum Berechtigungsmodelle brechen, wenn sie spät kommen
Das Grundproblem ist, dass die meisten frühen SaaS-Codebasen um eine einzige Entität gebaut sind: den Nutzer. Jede Ressource, ob Projekte, Reports, API-Keys oder Billing-Einstellungen, gehört einer Nutzerzeile. Wenn du später Teams hinzufügst, brauchst du eine Organisationsschicht zwischen Nutzern und Ressourcen, und das heißt, fast jede Tabelle deiner Datenbank, jede Autorisierungsprüfung deiner API und jede Frontend-Ansicht mit Besitzinformationen anzufassen.
Die Migration ist nicht nur technisch. Sie ist auch ein Produktproblem. Deine frühen Kunden haben sich an das Einzelnutzer-Modell angepasst. Manche haben geteilte Zugangsdaten für ihr Team angelegt, weil du ihnen keine Alternative gegeben hast. Sie auf ein sauberes Mehrbenutzer-Modell umzustellen erfordert Datenmigration, Kommunikation und bricht möglicherweise ihre aktuellen Arbeitsabläufe.
Nichts davon ist unüberwindbar, aber es kostet Zeit und Vertrauen. Das Organisationsmodell zuerst zu bauen, selbst in vereinfachter Form, vermeidet es vollständig.
Das Kern-Datenmodell
Das Fundament jedes Mehrbenutzer-B2B-SaaS besteht aus drei Entitäten: Organisationen, Mitgliedschaften und Rollen. Alles andere baut darauf auf.
Eine Organisation (manchmal Workspace, Account oder Tenant genannt) ist der oberste Eigentümer aller Geschäftsdaten. Nutzer besitzen keine Projekte oder Reports, Organisationen tun das. Ein Nutzer kann mehreren Organisationen angehören, was für Agenturen, Berater und alle relevant ist, die mehrere Kunden betreuen.
Eine Mitgliedschaft ist der Verknüpfungsdatensatz zwischen Nutzer und Organisation. Hier lebt die Rolle. Der Mitgliedschaftsdatensatz beantwortet die Frage: "In welchem Verhältnis steht diese Person zu dieser Organisation?" Er trägt typischerweise ein Feld role, ein Feld status (eingeladen, aktiv, gesperrt) und Zeitstempel.
Eine Rolle legt fest, was ein Mitglied tun darf. In den meisten B2B-SaaS-Produkten decken drei Rollen die Mehrheit der Fälle ab: Owner (volle Kontrolle inklusive Billing und Löschung), Admin (Mitglieder und Einstellungen verwalten, aber kein Billing) und Member (das Produkt nutzen). Brauchst du feinere Steuerung, kannst du eine Viewer-Rolle für Lesezugriff ergänzen.
In SQL ausgedrückt:
organizations (id, name, slug, created_at)
users (id, email, name, created_at)
memberships (id, organization_id, user_id, role, status, invited_by, created_at)
Alle Geschäftsdaten referenzieren dann organization_id, nicht user_id. Diese eine strukturelle Entscheidung macht Mandantenfähigkeit beherrschbar. Wie sich das in Symfony und Doctrine umsetzen lässt, zeigen praktische Beispiele rund um Multi-Tenant-SaaS-Architektur.
Den Einladungsfluss entwerfen
Bei Einladungen sparen die meisten Teams an der falschen Stelle und bereuen es. Ein robuster Einladungsfluss hat vier Zustände: ausstehend, angenommen, abgelaufen und widerrufen.
Wenn ein Admin alice@example.com einlädt, sollte dein System:
- Einen Mitgliedschaftsdatensatz mit
status: invitedundrole: member(oder der gewählten Rolle) anlegen. - Ein signiertes, zeitlich begrenztes Token erzeugen, entweder ein JWT oder ein zufälliges Token in der Datenbank mit einer Spalte
expires_at. - Eine E-Mail mit einem Link versenden, der dieses Token enthält.
Wenn Alice den Link anklickt:
- Ist das Token gültig und nicht abgelaufen: Nutzerkonto anlegen (oder mit einem bestehenden verknüpfen), Mitgliedschaft auf
status: activesetzen und sie ins Produkt weiterleiten. - Ist das Token abgelaufen: eine klare Meldung zeigen und eine neue Einladung anfordern lassen.
- Hat sie bereits ein Konto: Registrierung überspringen und direkt zum Organisationswechsel gehen.
Der letzte Punkt ist wichtig. Ein Nutzer kann mehreren Organisationen angehören. Nimmt er eine Einladung zu einer zweiten Organisation an, muss deine UI den Kontextwechsel abbilden, entweder beim Login oder über einen Workspace-Switcher in der Navigation. Das ist nicht komplex zu bauen, muss aber von Anfang an im Design stecken. Einen Workspace-Switcher nachträglich in eine Single-Organization-UI zu bringen ist ein kompletter Redesign.
Etwas, das oft übersprungen wird: widerrufene Einladungen. Merkt ein Admin, dass er die falsche Person eingeladen hat, sollte er die Einladung vor der Annahme zurückziehen können. Das heißt, der Einladungsdatensatz muss widerrufbar sein, und die Token-Validierung muss sowohl Ablauf als auch Widerrufsstatus prüfen.
Autorisierung auf API-Ebene
Das Einladungssystem steuert, wer hereinkommt. Die RBAC-Schicht steuert, was jemand drinnen tun darf.
Am besten funktioniert die Kombination aus Organisationskontext-Auflösung auf Middleware-Ebene und rollenbasierten Guards an einzelnen Endpunkten oder Controller-Aktionen.
Jeder authentifizierte Request sollte eine Organisationskennung tragen, entweder in einem Header (X-Organization-Id), einer Subdomain oder einem Pfadpräfix. Die Middleware löst diese zum Mitgliedschaftsdatensatz des authentifizierten Nutzers für diese Organisation auf und hängt Organisation und Rolle an den Request-Kontext.
Von da an sind Guards geradlinig:
// Symfony-Beispiel
#[Route('/api/members', methods: ['DELETE'])]
#[RequiresRole('admin')]
public function removeMember(Request $request): JsonResponse { ... }
Das Attribut RequiresRole (oder die entsprechende Middleware in deinem Stack) prüft die Rolle der aktuellen Mitgliedschaft und gibt bei Nichtübereinstimmung ein 403 zurück. Das hält Autorisierungslogik aus deiner Geschäftslogik heraus und macht sie leicht auditierbar.
Der häufigste Fehler auf dieser Ebene ist, Besitzprüfungen in der Geschäftslogik statt in der Autorisierungsschicht vorzunehmen. Wenn dein ProjectService::delete() prüft if ($project->getOwner() === $currentUser), bricht diese Prüfung in dem Moment, in dem du Organisationsbesitz einführst. Autorisierung sollte aufgelöst werden, bevor Geschäftslogik läuft, nicht in ihr.
Datenabfragen eingrenzen
Rollenprüfungen regeln, was jemand tun darf. Data Scoping regelt, was jemand sehen darf.
Jede Datenbankabfrage, die organisationsbezogene Daten liefert, muss einen Filter auf organization_id enthalten. Das ist nicht optional, es ist eine Sicherheitsgrenze. Ein bei Organisation A authentifizierter Nutzer darf niemals Daten von Organisation B abfragen können, selbst wenn er die richtige Ressourcen-ID errät.
Das praktische Muster ist ein Basis-Repository oder Query Builder, der den Organisations-Scope aus dem Request-Kontext immer anwendet:
// Jede Query startet vom gescopeten Repository
$projects = $this->projectRepository->findByOrganization($org)->findAll();
Row-Level Security in PostgreSQL bietet einen alternativen Ansatz, der den Scope auf Datenbankebene erzwingt. Ob das zu deinem Setup passt, hängt von der Komplexität deiner Queries und der Vertrautheit deines Teams mit RLS ab. Die Abwägungen rund um Postgres Row-Level Security für Multi-Tenant-SaaS sind es wert, im Detail betrachtet zu werden.
Billing und der Organisations-Owner
Billing verdient einen eigenen Abschnitt, weil hier die Owner-Rolle am meisten zählt.
In den meisten B2B-SaaS-Produkten hängt Billing an der Organisation, nicht am Nutzer. Abonnement, Zahlungsmittel und Rechnungshistorie gehören der Organisation. Der Haken: Jemand muss es besitzen, und wenn der ursprüngliche Owner das Unternehmen verlässt, brauchst du einen Weg, den Besitz zu übertragen.
Der minimal tragfähige Ansatz:
- Nur die Owner-Rolle hat Zugriff auf Billing-Einstellungen.
- Eine Organisation muss immer mindestens einen Owner haben. Eine Besitzübertragung setzt voraus, dass der empfangende Nutzer bereits Admin oder Member ist.
- Das Löschen einer Organisation erfordert eine explizite Bestätigung und kaskadiert korrekt (Abos kündigen, Daten gemäß deiner Aufbewahrungsrichtlinie löschen).
Diese Grenzfälle klingen offensichtlich, sind in frühen Produktdesigns aber durchgängig unterspezifiziert und werden in Produktion schmerzhaft nachzubessern.
Worauf Enterprise-Käufer tatsächlich achten
Wenn ein Enterprise-Käufer dein Produkt evaluiert, fragt sein IT-Team nach Zugriffskontrolle, bevor es nach Features fragt. Die Checkliste umfasst typischerweise: Können wir mehrere Nutzer haben, können wir steuern, was jeder Nutzer sieht und tut, können wir Zugriff sofort entziehen, wenn jemand geht, unterstützt ihr SSO, und können wir ein Audit-Log sehen, wer was getan hat?
Das oben beschriebene Organisations- und Rollenmodell deckt die ersten drei vollständig ab. SSO und Audit-Logs sind die natürlichen nächsten Schritte, sobald das Fundament steht. Wenn du von Anfang an für Enterprise baust, lohnt sich ein Blick auf Enterprise-SSO- und SCIM-Umsetzung, um zu verstehen, was nach RBAC kommt.
Der Punkt ist nicht, alles am ersten Tag zu bauen. Der Punkt ist, das Fundament so zu bauen, dass es dich nicht daran hindert, SSO oder Audit-Logs später ohne größere Umschreibungen zu ergänzen.
Die praktische Reihenfolge
Wenn du ein neues B2B-SaaS startest oder Mehrbenutzer-Unterstützung zu einem bestehenden hinzufügst, ist das eine sinnvolle Reihenfolge:
Erstens: Führe die Organisationsentität ein und migriere alle Geschäftsdaten auf Organisations-Scope. Tu das noch bevor Einladungen existieren. Ein Einzelnutzer-Produkt kann Organisationen mit einem Mitglied haben, das Verhalten ist identisch.
Zweitens: Baue das Mitgliedschaftsmodell und den Einladungsfluss. Halte die Rollenmenge klein (Owner, Admin, Member) und widerstehe dem Drang, individuelle Berechtigungen zu bauen, bevor du weißt, was Kunden wirklich brauchen.
Drittens: Ergänze Autorisierungs-Middleware und ersetze alle nutzerbezogenen Besitzprüfungen durch rollenbasierte Guards.
Viertens: Grenze alle Datenabfragen auf die Organisation ein und ergänze Tests, die Datenisolation über Organisationsgrenzen hinweg verifizieren.
Danach hast du ein Fundament, das SSO, Audit-Logs und feinere Berechtigungen trägt, wenn die Zeit dafür kommt, ohne größere Umschreibung.
Zusammenarbeit mit Spezialisten
Das Autorisierungsmodell richtig hinzubekommen ist eine dieser Entscheidungen, die oberflächlich einfach aussehen und sich in jede Richtung fortpflanzen, wenn man sie falsch trifft. Wir haben mandantenfähige SaaS-Backends für Kunden gebaut, bei denen das Berechtigungsmodell von Anfang an sorgfältig entworfen war, und wir haben Codebasen übernommen, bei denen das nicht der Fall war. Der Unterschied in den Kosten für Enterprise-Features ist erheblich.
Wenn du ein neues Produkt entwirfst oder Mehrbenutzer-Unterstützung in einem bestehenden angehst: wolf-tech.io bietet Architekturberatung und Custom Software Development speziell für SaaS-Produkte. Melde dich unter hello@wolf-tech.io, wir sprechen dein Modell gern durch, bevor du es baust.

