You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Allow service account users to be stored in external user storage providers
#49738
Service account users (service-account-<clientId>) are always created in local JPA storage, even when a realm uses an external UserStorageProvider for all other users. UserStorageManager.addUser hard-codes a local-storage path for usernames with the service-account prefix, and getServiceAccount only queries local storage.
This is a creates issues for deployments that:
Run Keycloak with a read-only or minimal local DB and want all user identities (including machine identities) in a single external store.
Need service accounts to participate in role/group mappings that are authoritative in the external store
Want to audit, replicate, or manage service-account principals with the same tooling as regular users
Proposed solution
Updated Interface
Add an optional capability interface UserServiceAccountProvider (in server-spi-private) that a UserStorageProvider can implement:
addUser: for service-account usernames. To do this, iterate through the enabled providers implementing UserServiceAccountProvider in priority order; first non-null wins; fall back to local storage if none claim it.
getServiceAccount: check local storage first (which preserves behavior for existing realms with locally-stored service accounts), then iterate though the UserServiceAccountProvider implementations.
removeUser: run federated-storage preRemove cleanup for externally-stored service accounts (previously skipped for all service accounts).
Relax the "do not override" javadoc on get/setServiceAccountClientLink so implementers can persist the client link in their backing store.
Backward compatibility
Realms without a provider implementing this interface are unaffected — service accounts continue to be created and looked up in local storage. Existing locally-stored service accounts remain resolvable because lookup checks local storage first. The interface is placed in server-spi-private and is not a stable public SPI.
Alternatives
We considered routing service accounts through the existing UserRegistrationProvider path but rejected it because most external stores should not receive service accounts by default; an explicit opt-in interface is safer.
We also considered a per-client config flag pointing at a storage provider which is more flexible but significantly more invasive (admin UI, REST, migration). This could be layered on later if needed.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Proposal
Service account users (
service-account-<clientId>) are always created in local JPA storage, even when a realm uses an external UserStorageProvider for all other users. UserStorageManager.addUser hard-codes a local-storage path for usernames with the service-account prefix, and getServiceAccount only queries local storage.This is a creates issues for deployments that:
Proposed solution
Updated Interface
Add an optional capability interface
UserServiceAccountProvider(in server-spi-private) that aUserStorageProvidercan implement:Implementation Details
UserStorageManagerchanges:addUser: for service-account usernames. To do this, iterate through the enabled providers implementingUserServiceAccountProviderin priority order; first non-null wins; fall back to local storage if none claim it.getServiceAccount: check local storage first (which preserves behavior for existing realms with locally-stored service accounts), then iterate though theUserServiceAccountProviderimplementations.removeUser: run federated-storage preRemove cleanup for externally-stored service accounts (previously skipped for all service accounts).AbstractUserAdapter/AbstractUserAdapterFederatedStoragechangesget/setServiceAccountClientLinkso implementers can persist the client link in their backing store.Backward compatibility
Realms without a provider implementing this interface are unaffected — service accounts continue to be created and looked up in local storage. Existing locally-stored service accounts remain resolvable because lookup checks local storage first. The interface is placed in server-spi-private and is not a stable public SPI.
Alternatives
UserRegistrationProviderpath but rejected it because most external stores should not receive service accounts by default; an explicit opt-in interface is safer.All reactions