Wenn wir eine LDAP- bzw. AD-Federation in Keycloak einrichten, taucht bei uns im Team immer wieder dieselbe Diskussion auf: Was genau bewirkt eigentlich der Parameter EDIT_MODE? Und wie unterscheiden sich READ_ONLY, WRITABLE und UNSYNCED konkret voneinander? In der Doku liest sich das auf den ersten Blick eindeutig, aber sobald es um Detailfragen geht – Kann ich Custom-Attribute setzen? Funktioniert ein Passwort-Reset? Werden Rollen zugeordnet? – wird es erstaunlich schnell unpräzise.
Erschwerend kommt hinzu: Keycloak zeigt dir nirgends direkt an, welche Nutzer aus dem AD eigentlich schon importiert sind und welche nicht. Suchst du einen Nutzer über die Admin Console, wird in genau diesem Moment der LDAP-Lookup durchgeführt – und falls Import Users = On gesetzt ist, wird der gesuchte Nutzer dabei auch gleich importiert. Dasselbe passiert, wenn du Nutzer über die Admin-REST-API abfragst. Es gibt also keinen einfachen Weg, sich einen ehrlichen Überblick zu verschaffen, ohne dabei den Zustand selbst zu verändern.
Am Ende haben wir deshalb direkt in der Datenbank nachgesehen – in user_entity und den zugehörigen FED_USER_*-Tabellen. Was wir dabei gelernt haben, fassen wir hier zusammen.
Hinweis: Dieser Beitrag bezieht sich auf die Funktionsweise von Keycloak 26.6.4. In anderen Versionen kann sich das Verhalten im Detail unterscheiden.
Fangen wir mit Import an
Bevor EDIT_MODE überhaupt relevant wird, lohnt sich ein Blick auf Import Users.

Ist Import = off gesetzt, werden AD-Nutzer nie in der zentralen user_entity-Tabelle angelegt. Das hat spürbare Konsequenzen: Über das Admin Interface lassen sich diesen Nutzern zum Beispiel keine Rollen zuordnen, und viele Required Actions schlagen fehl – häufig mit der Fehlermeldung „User is read-only“. Das ist grundsätzlich auch korrekt, denn der Nutzer existiert in Keycloak eigentlich gar nicht als eigenständiger Datensatz.
Konsequent ist Keycloak dabei aber nicht: Ein Nutzer kann sich trotzdem über die Account Console selbst ein 2FA-Verfahren einrichten. Dahinter steckt ein separater Mechanismus, den Keycloak „Federated Storage“ nennt – eine Reihe eigener Tabellen (FED_USER_CREDENTIAL, FED_USER_ROLE_MAPPING usw.), die Keycloak-spezifische Daten zu einem Nutzer speichern können, ganz ohne dass dafür ein vollständiger user_entity-Eintrag existieren muss. In der Praxis ist das aber ein unvollständiger, teils fehlerbehafteter Mechanismus – auf den wir in einem separaten Beitrag nochmal genauer eingehen.
Unser Fazit: Import = off lässt sich in der Regel ausschließen, außer du willst über Keycloak wirklich nur eine reine AD-Anmeldung abbilden und darüber hinaus keinerlei weitere Daten zu einem Nutzerkonto erheben oder verarbeiten. Für den Rest dieses Beitrags gehen wir deshalb davon aus, dass Import Users = on gesetzt ist. Erst damit ist grundsätzlich möglich, was man von einer vollwertigen Nutzerverwaltung erwartet: Rollen lassen sich zuordnen, viele Required Actions greifen wie vorgesehen, und MFA-Verfahren können ausgerollt werden. Diese grundlegenden Funktionen setzt Keycloak also erst frei, wenn der Nutzer auch tatsächlich importiert wird.
EDIT_MODE = READ_ONLY
Dieser Modus bedeutet: Es wird ausschließlich aus dem LDAP gelesen, nichts geht zurück. In der Praxis führt das dazu, dass die Nutzerattribute eines Accounts komplett ausgegraut sind – völlig in Ordnung, das ist ja auch der Sinn der Sache.

Etwas ärgerlich wird es bei Custom-Attributen: Die sind ebenfalls ausgegraut, selbst wenn sie überhaupt nicht per LDAP-Mapper an AD gebunden sind. Eigentlich würde man erwarten, dass nur die tatsächlich aus AD stammenden Felder read-only sind, während rein Keycloak-eigene Metadaten weiterhin frei erhoben werden können. Das ist aber nicht der Fall – der Schreibschutz greift pauschal auf Ebene des gesamten Nutzerobjekts, nicht pro Attribut. Aus unserer Sicht ist das gewissermaßen ein Bug in Keycloak, kein bewusstes Designziel.
Über diese Custom-Attribute-Einschränkung hinaus ist uns bei READ_ONLY kein weiterer Nachteil bekannt. Alle anderen Daten wie Rollenzuordnung, MFA-Methoden usw. lassen sich problemlos erheben und verbleiben in der Keycloak-DB – sie haben schlicht keinen Bezug zum EDIT_MODE und sind davon deshalb auch nicht betroffen.
EDIT_MODE = WRITABLE
Hier können Werte aus dem AD auch von Keycloak aus geändert werden – und die Änderungen werden tatsächlich zurück ins LDAP geschrieben.

Interessant wird WRITABLE vor allem für den Passwort-Reset: Nur in diesem Modus kann ein neues Passwort tatsächlich im AD gesetzt werden. Nebenbei ist WRITABLE auch der einzige Modus, in dem sich Custom-Attribute problemlos setzen lassen – ohne die READ_ONLY-Einschränkung von oben.
Der typische Zielkonflikt: Passwort-Reset ja, sonst aber möglichst read-only
In der Praxis trifft man häufig auf folgende Anforderung: AD soll führendes System bleiben, allgemeine Nutzerattribute sollen über Keycloak also nicht änderbar sein – ein Passwort-Reset über Keycloak soll aber trotzdem möglich sein. Ein möglicher Workaround: Dem LDAP-Bind-Account der User-Federation im AD wirklich nur die Rechte einräumen, die für einen Passwort-Reset nötig sind (nicht mehr).
Das funktioniert grundsätzlich, hat aber einen Haken: Sobald jemand versucht, in Keycloak z. B. Vorname oder Nachname zu ändern, versucht Keycloak brav, diese Änderung ins AD zurückzuschreiben – und scheitert, weil der Bind-Account dafür keine Rechte hat. Diese Fehlermeldung landet nicht nur im Server-Log, sondern taucht auch direkt in der Admin-GUI auf und sorgt für Verwirrung. Dem lässt sich entgegenwirken, indem man die entsprechenden Felder (Vorname, Nachname, usw.) in den User-Profile-Einstellungen des Realms zusätzlich auf „nur lesbar“ setzt – dann kommt gar nicht erst jemand auf die Idee, sie zu ändern.
Ganz sauber ist auch dieser Workaround nicht – er kuriert nur ein Symptom auf UI-Ebene, eine wirklich saubere Lösung würde eine Produktanpassung erfordern. Als praktikabler Workaround reicht er in den meisten Fällen aber aus.
EDIT_MODE = UNSYNCED
Allein der Name klingt erstmal nicht vertrauenerweckend – eine „ungesynchte“ Datenbasis verheißt intuitiv nichts Gutes. Schauen wir uns aber genauer an, was dahintersteckt.

UNSYNCED verhält sich im Kern wie READ_ONLY: Die Daten stammen aus dem AD, nichts wird zurückgeschrieben. Der entscheidende Unterschied: Anders als bei READ_ONLY lassen sich die importierten Einträge in Keycloak trotzdem bearbeiten. Die Änderungen bleiben dann aber ausschließlich lokal in der Keycloak-Datenbank und weichen ab diesem Zeitpunkt vom Stand im AD ab.
Auch ein Passwort-Reset funktioniert unter UNSYNCED – aber eben nur lokal: Das neue Passwort wird in Keycloaks eigener Datenbank gespeichert und dort auch für künftige Logins verwendet, das Passwort im AD selbst bleibt davon komplett unberührt. Ein AD-seitiger Passwort-Reset ist über UNSYNCED also nicht möglich, ein lokaler Keycloak-Passwort-Reset dagegen schon.
Wozu also dieser Modus? Eigentlich nur dann sinnvoll, wenn AD nicht (mehr) führend sein soll: Man importiert die Nutzerbasis einmalig, verabschiedet sich danach aber strategisch vom AD als Datenquelle – etwa im Rahmen einer Migration, wenn AD langfristig abgelöst werden soll. Soll AD dagegen dauerhaft führendes System bleiben, ist dieser Modus für euch schlicht nicht relevant. Ein netter Nebeneffekt in Migrationsszenarien: Nach dem initialen Import ist Keycloak für den laufenden Betrieb nicht mehr von der Verfügbarkeit des AD abhängig.
Die Übersicht
| READ_ONLY | WRITABLE | UNSYNCED | |
| Import Users = on | AD ist führendes System, Daten werden übernommen und können nicht editiert werden. Keycloak-spezifische Daten (Rollenzuordnung, MFA-Verfahren, emailVerified) können erhoben werden – außer generische Custom-Attribute (gewissermaßen ein Bug). | Alle Attribute (AD-gemappt und Custom) frei editierbar, gemappte syncen zurück nach AD. Passwort-Reset syncet ebenfalls nach AD – erfordert korrekte AD-ACL-Rechte für den Bind-Account. | Alle Attribute (AD-gemappt und Custom) editierbar, Änderungen bleiben aber ausschließlich in der Keycloak-DB, nichts syncet zurück. Passwort-Reset setzt ein neues Passwort lokal in Keycloak (nicht im AD). |
| Import Users = off | Keycloak wird praktisch nur zur AD-Anmeldung genutzt. Da der Nutzer nicht in der Keycloak-DB geführt wird, können keine Keycloak-spezifischen Daten erhoben werden (z. B. Rollenzuordnung, MFA-Verfahren). | Wie READ_ONLY, zusätzlich sind AD-Attribute von Keycloak aus editierbar. Password-Reset ist möglich. | Unsinnig – ohne Import gibt es keine lokale Kopie, die „entkoppelt“ bleiben könnte. |
Unser Fazit
Import sollte in der Regel aktiviert sein – ohne Import lassen sich für einen Nutzer praktisch keine Daten erheben, weder MFA-Verfahren noch Rollenzuordnung funktionieren zuverlässig. Nutzt ihr Keycloak wirklich nur als reine AD- bzw. Kerberos-Anmeldung ohne jede weitere Datenerhebung, kann Import = false infrage kommen. In den allermeisten Fällen werdet ihr die Nutzer aber importieren wollen.
Ist das geklärt, bleibt die Frage nach dem passenden EDIT_MODE: Braucht ihr keinen Passwort-Reset über Keycloak und habt auch keine Custom-Attribute im Spiel, reicht READ_ONLY völlig aus. Sobald einer von beidem gebraucht wird, führt kein Weg an WRITABLE vorbei.
Der Anwendungsfall „nur Passwort-Reset ermöglichen, alle anderen Daten sollen read-only bleiben“ lässt sich in Keycloak leider nur unsauber abbilden – es gibt dafür keinen eigenen, granularen Modus. Ihr müsst auf WRITABLE gehen, solltet dann aber unbedingt sicherstellen, dass die entsprechenden Felder im User Profile auf „nur lesbar“ gesetzt sind, um überflüssige Fehlermeldungen bei versuchten Änderungen zu vermeiden.
