What Is a Custom User Storage Provider in Keycloak? Teaching Keycloak to Speak Your Database's Language
A complete, no-code walkthrough of how Keycloak lets you plug in an existing user directory — a legacy database, an internal HR system, a proprietary identity store — without migrating a single user record.
Imagine a company merges with another that has run its own employee directory for twenty years, stored in a system nobody wants to touch. Rather than forcing every employee to be re-created in a brand-new system overnight — a risky, disruptive migration — a good IT team builds a translator: something that lets the new company’s tools ask “does this employee exist? what’s their password? what team are they on?” and get real answers straight from the old system, live, without copying anything over. A Custom User Storage Provider is exactly that translator, built for Keycloak. It lets Keycloak treat an external system as if it were one of its own user stores, without requiring that system’s data to ever be duplicated into Keycloak itself.
1What Is a Custom User Storage Provider?
Before diagrams and architecture, let’s build a clear mental model of the problem this feature solves.
The problem: not every user lives in Keycloak’s own database
By default, Keycloak stores users — their credentials, profile attributes, and role assignments — in its own internal database. That works well for new deployments. But many organizations already have users living somewhere else: a decades-old relational database, a proprietary HR platform, a legacy authentication system tied to a mainframe. Migrating all of that data into Keycloak’s own store is often risky, sometimes technically difficult, and occasionally simply not allowed by policy. Custom User Storage Providers exist precisely for this situation.
Think of a universal power adapter you take when traveling. It doesn’t rewire the electrical outlet in your hotel room — it simply translates between the shape of your plug and the shape of the wall socket, letting your device work seamlessly with infrastructure it was never originally designed for. A Custom User Storage Provider does the same job between Keycloak and whatever system your organization’s users actually live in.
The formal definition
A User Storage Provider is an implementation of Keycloak’s User Storage SPI (Service Provider Interface) that allows an external system to act as a source of user data for a realm. A Custom User Storage Provider is one an organization builds itself — as opposed to Keycloak’s built-in providers for common systems like LDAP directories — to connect to a bespoke or proprietary user store that Keycloak has no ready-made integration for.
This is different from Identity Brokering, which redirects the user to log in at an entirely separate authorization server. A User Storage Provider keeps the login experience inside Keycloak itself — Keycloak just fetches the underlying user data from somewhere else behind the scenes.
What “federation” really means here
This capability is often described as user federation, because it lets Keycloak federate — that is, incorporate and present as its own — user records that physically live in an external system. From the perspective of any application relying on Keycloak, a federated user looks exactly like a normal Keycloak user; the federation happens transparently underneath.
LDAP Provider
Keycloak ships with a ready-made provider for LDAP and Active Directory, since these are extremely common enterprise directory systems.
Legacy SQL Database
An organization with users stored in an old, in-house relational database needs a Custom User Storage Provider, since no built-in option matches its proprietary schema.
A User Storage Provider is not the same as importing users once via a bulk migration script. Federation is a live, ongoing connection — Keycloak asks the external system for data on demand, rather than copying it in a single one-time operation.
Why this matters beyond just convenience
Avoiding a bulk migration isn’t only about saving engineering effort — it’s often about risk. A one-time migration of sensitive credential and profile data carries real chances of data loss, corruption, or a window where two systems disagree about who a user is and what they’re allowed to do. Keeping the external system as the live source of truth, and simply teaching Keycloak to ask it questions, sidesteps that entire category of migration risk, at the cost of an ongoing dependency on that external system’s availability — a trade-off explored in depth later in this post.
2Architecture & Components
A Custom User Storage Provider isn’t one single piece of code — it’s a small set of cooperating parts that plug into Keycloak’s provider framework.
The Service Provider Interface (SPI) model
Keycloak is built around a plugin architecture called SPIs, which let developers extend or replace specific pieces of Keycloak’s behavior without modifying Keycloak’s own codebase. The User Storage SPI is one such extension point, specifically dedicated to sourcing user data from external systems.
Provider Factory
The piece responsible for creating instances of the provider and exposing its configuration options in the Keycloak admin console.
Provider Instance
The actual runtime object that talks to the external system on behalf of a specific realm, fulfilling requests for user lookup, credential checks, and attribute retrieval.
Capability Interfaces
Optional interfaces a provider can additionally implement to support lookup by username, lookup by email, credential validation, or full CRUD management of users.
External Data Source
The actual system being federated — a database, an internal API, a proprietary directory — that the provider’s code knows how to query.
How the pieces fit together
Picture Keycloak’s core as a hotel front desk that doesn’t personally know every guest but knows exactly which department to call to check. When a guest’s name doesn’t match anyone in the front desk’s own guest list, the front desk calls the affiliated corporate housing office (the external data source) through a dedicated phone line (the provider instance) built specifically for that purpose (the provider factory’s configuration). The guest still checks in through the same front desk, never realizing their record actually lives somewhere else entirely.
flowchart LR
KC[Keycloak Core] -->|user lookup request| SPI[User Storage SPI]
SPI --> PF[Provider Factory]
PF --> PI[Provider Instance]
PI -->|query| EXT[External Data Source
e.g. legacy database]
EXT -->|user record| PI
PI -->|federated user| KC
Optional capabilities a provider can implement
Not every provider needs to do everything. A provider might only support looking users up by username, treating the external system as strictly read-only — useful when the external system is authoritative and shouldn’t be modified through Keycloak at all. Another provider might additionally implement full user management, letting administrators create, update, and delete records in the external system directly through the Keycloak admin console.
Registering a provider with a realm
Once a provider’s code is deployed alongside Keycloak, an administrator enables it for a specific realm through the User Federation section of the admin console, configuring connection details specific to that provider — such as a database connection string, an internal API endpoint, or authentication credentials the provider itself needs to reach the external system. A single realm can have multiple providers active at once, each potentially responsible for a different subset of users or a different external system entirely.
Priority ordering among multiple providers
When more than one provider is configured for the same realm, Keycloak consults them in a defined priority order until one recognizes the requested user. This lets an organization layer several external sources together — for example, checking a primary HR database first, and falling back to a secondary legacy system only if the first doesn’t recognize the username — without needing a single provider to understand every possible source at once.
3Internal Working
What actually happens inside Keycloak the moment it needs information about a federated user?
A request needs user data
A login attempt, an admin console search, or an API call triggers Keycloak’s core to look for a user by username, email, or another identifier.
Keycloak checks its own local store first
Keycloak looks in its internal database before reaching out anywhere else, since not every user necessarily comes from an external provider.
If not found locally, registered providers are consulted
Keycloak iterates through the realm’s configured User Storage Providers, asking each one in turn whether it recognizes the requested identifier.
The provider queries its external system
The custom provider’s code translates Keycloak’s request into whatever query language or API call the external system understands, and retrieves the matching record.
The result is adapted into a Keycloak user model
The provider maps the external record’s fields into the shape Keycloak expects internally, so the rest of the system can treat it identically to a native user.
Credential validation, if applicable
If the request involves a login, the provider’s credential validation logic checks the submitted password against the external system’s own stored credential, without Keycloak ever seeing or storing that credential itself.
Think of a multilingual concierge fielding a guest’s question. First, the concierge checks their own notes (Keycloak’s local store). If the answer isn’t there, they call one of several specialist departments they know about (the registered providers), and the one that recognizes the guest’s name (the matching provider) makes the actual call to the guest’s home office (the external system) to get the real answer, then translates it back into terms the concierge and guest both understand.
Caching to avoid hammering the external system
Because querying an external system on every single request could be slow or place heavy load on that system, Keycloak supports caching federated user data locally for a configurable period. Cached data is periodically refreshed or invalidated, striking a balance between performance and staying reasonably current with changes made directly in the external system.
Caching behavior is itself configurable per provider — some deployments cache aggressively for performance, while others disable caching entirely for external systems where staying perfectly current matters more than speed.
Handling lookups that don’t match anything
Not every lookup succeeds. When neither Keycloak’s local store nor any registered provider recognizes a given username or email, the request simply fails as “user not found,” exactly as it would in a purely native Keycloak setup. Providers are typically written to fail this check quickly and cheaply, since a busy login page might be checking many attempted usernames that don’t correspond to any real account, and a slow “not found” response is just as costly to performance as a slow successful one.
Mapping fields between two different data shapes
An external system’s data rarely lines up perfectly with Keycloak’s own expectations for a user record. A legacy database might store a name as a single combined field, while Keycloak expects separate first and last name attributes; it might use a numeric employee ID as its primary identifier, where Keycloak expects a username. Part of building the provider is deciding, deliberately, how these mismatches get resolved — decisions that, once made, become a durable part of how that organization’s identities are represented going forward.
4Data Flow & Lifecycle
Let’s trace a full request end to end, using a realistic scenario: a user logging in whose account lives entirely in a legacy HR database.
sequenceDiagram
participant User
participant KC as Keycloak
participant Provider as Custom Storage Provider
participant HR as Legacy HR Database
User->>KC: Enter username and password
KC->>KC: Check internal user store (not found)
KC->>Provider: Delegate lookup for username
Provider->>HR: Query for matching employee record
HR-->>Provider: Return employee data
Provider-->>KC: Map to Keycloak user model
KC->>Provider: Validate submitted password
Provider->>HR: Check credential against stored value
HR-->>Provider: Valid / Invalid
Provider-->>KC: Credential result
KC-->>User: Login success or failure
Lifecycle of a federated user’s data
Discovered
The first time Keycloak needs a user not in its local store, the provider locates the matching record in the external system.
Represented
Keycloak creates a lightweight local representation linking to the external record, so the rest of the system has something to reference.
Cached (optional)
Depending on configuration, the retrieved data may be cached locally for a period to reduce repeated external queries.
Refreshed or Invalidated
The cache expires or is invalidated, and the next request re-queries the external system to reflect any changes made there directly.
If a user’s data changes directly in the external system — a password reset, an attribute update — but Keycloak’s cache hasn’t expired yet, Keycloak may briefly continue to reflect the stale, previously cached version until the cache refreshes.
Import versus no-import providers
Some deployments configure a provider to “import” federated users into Keycloak’s local store on first lookup, after which Keycloak treats that user largely as its own, periodically re-syncing from the source. Others use a strict no-import model, where Keycloak never persists the user’s data locally at all and always queries the external system fresh. The right choice depends on how authoritative and available the external system is expected to remain over time.
Choosing between import and no-import in practice
An import model tends to suit organizations that expect the external system to eventually be retired — imported users gradually become fully native Keycloak users over time, easing the path toward decommissioning the legacy source entirely. A no-import model suits the opposite situation: an external system that will remain the permanent source of truth indefinitely, where treating Keycloak’s copy as anything more than a transient, cached view would risk the two systems drifting out of sync.
5Common Provider Patterns
Custom User Storage Providers aren’t all built the same way — the right shape depends on what the external system can and should be allowed to do.
Read-Only Lookup Provider
Only supports finding users and validating credentials, treating the external system as an authoritative source that should never be modified through Keycloak.
Read-Write Management Provider
Supports full user creation, updates, and deletion, letting administrators manage the external system’s users entirely through Keycloak’s own admin console.
Credential-Delegation-Only Provider
Delegates only password validation to the external system, while user profile data itself is imported and managed natively within Keycloak.
Attribute-Enrichment Provider
Supplements a user who already exists in Keycloak’s local store with additional attributes pulled from an external system, rather than owning the user’s core identity at all.
Comparing the patterns side by side
| Pattern | External System Modified? | Typical Use |
|---|---|---|
| Read-Only Lookup | No | Authoritative legacy systems that must not change |
| Read-Write Management | Yes | Fully replacing a legacy admin tool with Keycloak’s console |
| Credential-Delegation-Only | No (read only for auth) | Gradual migration while trusting the old password store |
| Attribute-Enrichment | No | Pulling extra profile data without owning identity |
6Custom Providers vs. the Alternatives
It’s worth seeing this approach next to the other ways organizations connect Keycloak to existing user data.
Bulk Migration
Exporting all users from the legacy system and importing them into Keycloak’s own store once. Simple conceptually, but risky for large datasets and creates two copies of the truth during any transition period.
Identity Brokering
Redirecting users to authenticate at the external system’s own login page, then bringing them back to Keycloak. Works well when the external system already has its own full authentication flow, but changes the login experience users see.
Built-In LDAP Provider
Keycloak’s ready-made LDAP integration, ideal when the external system is a standard LDAP or Active Directory directory rather than something proprietary.
| Approach | Login Experience Stays in Keycloak? | Requires Migrating Data? | Fits Proprietary Systems? |
|---|---|---|---|
| Bulk Migration | Yes | Yes | Yes, after migration |
| Identity Brokering | No | No | Depends on external login flow |
| Built-In LDAP Provider | Yes | No | Only for LDAP/AD |
| Custom User Storage Provider | Yes | No | Yes |
The pattern across every alternative is familiar: each solves part of the puzzle while giving something else up — either the unified login experience, or the ability to avoid migration, or compatibility with a non-standard system. A Custom User Storage Provider is the option organizations reach for specifically when they need all three at once and no built-in provider already covers their particular external system.
Combining approaches in a single realm
These options aren’t always mutually exclusive. A realm might use the built-in LDAP provider for its standard corporate directory, a custom provider for a legacy proprietary system acquired through a merger, and identity brokering for a small set of external partner organizations that already run their own full authentication systems — all coexisting within the same realm, each handling the population of users it’s best suited for.
7Advantages, Disadvantages & Trade-offs
Building a custom integration is powerful, but it comes with genuine engineering and operational responsibilities.
Advantages
- No risky, one-time bulk migration of sensitive user data is required
- Users experience a single, consistent login flow through Keycloak regardless of where their data actually lives
- The external system can remain the single source of truth for as long as needed
- Supports a gradual, incremental migration path rather than an all-or-nothing cutover
- Reuses Keycloak’s full authentication and session features on top of externally sourced identities
Disadvantages / Trade-offs
- Requires custom development effort to implement and maintain the provider code
- Every relevant login or lookup now depends on the external system’s availability and performance
- Caching strategy must be tuned carefully to balance freshness against load on the external system
- Debugging authentication issues now spans two systems instead of one
Building a translator booth at a conference means every attendee gets a seamless experience regardless of language — but it also means the conference now depends on the translator being present, prepared, and able to keep up in real time. A Custom User Storage Provider carries the same kind of ongoing operational responsibility.
Weighing the trade-off honestly
The right decision usually comes down to how long the external system is expected to remain in place, and how much engineering capacity exists to build and maintain the provider well. A system being retired within a year might not justify the investment of a custom provider at all — a simpler, well-planned bulk migration could be less overall effort. A system expected to remain authoritative for the foreseeable future, by contrast, often makes the ongoing maintenance cost of a custom provider clearly worthwhile compared to the alternative of forcing a migration that isn’t really wanted.
8Security Considerations
Because a custom provider sits directly in the authentication path, its implementation quality has a direct impact on the security of every login it handles.
Improper Credential Handling
A provider that logs, caches, or mishandles submitted passwords while validating them against the external system introduces a new place credentials could leak.
Insecure Connection to the External System
If the provider communicates with its external data source over an unencrypted or poorly authenticated channel, that connection becomes a weak link in the overall authentication chain.
Overly Permissive Write Access
Implementing full read-write management when only read access is actually needed unnecessarily expands what a compromised Keycloak instance could do to the external system.
Stale Cached Permissions
Caching user data too aggressively can mean a revoked or disabled account in the external system continues to be treated as valid by Keycloak until the cache expires.
A Custom User Storage Provider should implement only the capabilities actually required — a read-only lookup provider should not also implement write access “just in case,” since every additional capability is additional attack surface.
Treating the provider as part of the trusted computing base
Because the provider’s code runs with direct access to authentication decisions, it deserves the same code review, testing, and security scrutiny as any other authentication-critical component — not the lighter treatment sometimes given to internal integration glue code. A vulnerability in the provider is functionally a vulnerability in Keycloak’s login path itself.
The service account problem
Because a provider typically needs its own credentials to query the external system — a service account, an API key, a database connection string — those credentials become a high-value target in their own right. They should be stored using Keycloak’s own credential vault or an equivalent secrets management approach, never embedded directly in configuration files or source code, and rotated on the same schedule an organization applies to its other privileged service accounts.
9Monitoring, Logging & Metrics
Because a custom provider introduces a dependency on an external system, operating it well means watching that dependency closely.
What to watch
External Query Latency
Since every uncached lookup depends on the external system responding, slow queries there directly slow down login for real users.
External System Error Rate
A rising rate of failed queries can indicate connectivity problems, credential expiry for the provider’s own service account, or capacity issues on the external side.
Cache Hit Rate
A very low hit rate suggests the cache configuration isn’t matched to actual usage patterns, driving unnecessary load on the external system.
Failed Credential Validations
Tracking this separately from general login failures helps distinguish genuine bad password attempts from a broken connection to the external validation source.
What to log
Recording which provider handled a given lookup, how long the external query took, and whether it succeeded or failed gives administrators a clear trail for diagnosing authentication problems that span both Keycloak and the external system — without which a login failure could be misdiagnosed as a Keycloak bug when the real cause lies entirely on the other side of the integration.
Setting up early warning for external dependency health
Because the external system’s health is now directly tied to Keycloak’s ability to authenticate users, it’s worth alerting on that system’s own health signals — not just Keycloak’s — well before a full outage occurs. A gradually rising query latency on the external side, for instance, is a useful early warning that gives an operations team time to investigate before it turns into visible login failures for real users.
10Design Patterns & Anti-Patterns
Some ways of building a custom provider age well as usage scales. Others quietly become fragile.
Problem
Querying the external system directly on every single login attempt with no caching at all, “to always be perfectly current.”
Why It’s Harmful
Under real load, this can overwhelm the external system and make login latency directly dependent on that system’s worst-case response time, degrading the experience for every user.
Correct Approach
Introduce a deliberately short, carefully chosen cache window that balances freshness against load, rather than treating caching as something to avoid entirely.
Problem
Implementing the provider without any handling for the external system being temporarily unavailable.
Why It’s Harmful
A brief outage or network blip on the external side becomes a full authentication outage for every federated user, even though Keycloak itself is running fine.
Correct Approach
Design the provider to fail gracefully and predictably — clear error messages, sensible timeouts — and consider whether recently cached data can safely serve a short outage window.
Patterns worth adopting
Read-Only First, Expand Later
Start with a read-only provider even if write support is eventually planned, proving the integration is reliable before granting it the ability to modify the external system.
Thin Adapter, Thick External Logic
Keep the provider itself focused purely on translating between Keycloak’s expectations and the external system’s interface, rather than embedding significant business logic that belongs in the external system.
Problem
Writing the provider’s mapping logic to assume the external system’s data will always be perfectly well-formed and complete.
Why It’s Harmful
Real legacy systems accumulate messy edge cases over years — missing fields, inconsistent formats, duplicate records — and a provider that doesn’t account for this can fail unpredictably or, worse, silently map bad data into a user record that behaves incorrectly.
Correct Approach
Build defensive handling for missing or malformed fields directly into the mapping logic, with clear, loud failures for genuinely unusable records rather than silent, incorrect defaults.
11Best Practices & Common Mistakes
A checklist-style chapter distilling the operational wisdom from the sections above.
| Best Practice | Common Mistake It Prevents |
|---|---|
| Implement only the capabilities actually needed | Unnecessary write access expanding the attack surface |
| Tune caching deliberately based on real usage | Either overloading the external system or serving stale data |
| Handle external system outages gracefully | A minor external blip becoming a full authentication outage |
| Log external query performance and outcomes separately | Misdiagnosing external issues as Keycloak bugs |
| Secure the connection to the external system | A weak link introduced right in the authentication chain |
| Review the provider’s code with the same rigor as core authentication code | Treating integration glue code as lower-risk than it actually is |
Test the provider’s behavior specifically under external-system failure conditions before going live — a login system that only works when everything upstream is healthy hasn’t really been tested at all.
Planning for eventual retirement
Even a well-built custom provider is often, by design, a bridge rather than a permanent destination. Teams that plan from the outset for how and when the external system might eventually be retired — whether through gradual import into Keycloak’s native store or a deliberate future migration — tend to avoid the common trap of a “temporary” integration quietly becoming permanent infrastructure nobody budgeted to maintain indefinitely.
12Real-World & Industry Examples
Custom User Storage Providers show up wherever an organization’s real user data lives somewhere Keycloak doesn’t natively understand.
Mergers and Acquisitions
Companies integrating a newly acquired organization’s employee directory often use a custom provider to bring those employees into a unified single sign-on experience immediately, without waiting for a lengthy data migration project to complete first.
Legacy Government and Enterprise Systems
Long-running institutional systems, sometimes decades old, frequently can’t be easily migrated due to regulatory, contractual, or technical constraints — a custom provider lets modern applications adopt Keycloak-based authentication while that legacy system remains untouched underneath.
Multi-Product Companies with Separate User Bases
Organizations that acquired or built several products, each with its own historical user store, use custom providers to unify login across all of them under one Keycloak realm, without forcing every product’s user base to be consolidated into a single database first.
Regulated Industries with Data Residency Constraints
Some organizations are required to keep certain user data within a specific system or jurisdiction for compliance reasons — a custom provider allows Keycloak to authenticate against that data without ever copying it outside its required boundary.
Higher Education Systems
Universities often maintain a long-standing student information system predating modern identity standards — a custom provider lets new campus applications authenticate against that existing system while a broader modernization effort proceeds at its own pace.
Telecommunications and Utilities
Companies with decades-old customer or subscriber databases use custom providers to bring modern self-service portals under unified authentication without touching the underlying billing and account systems those records are tightly coupled to.
13Frequently Asked Questions
No — LDAP integration uses Keycloak’s built-in provider designed specifically for LDAP and Active Directory. A Custom User Storage Provider is something an organization builds for a system with no existing built-in integration.
Not necessarily — it depends on whether the provider is configured to import users locally or to always query the external system fresh, without persisting a local copy.
Yes, if it implements the relevant capability interfaces — though many deployments deliberately keep the provider read-only to avoid unnecessarily expanding what Keycloak can change in the external system.
Behavior depends entirely on how the provider is implemented — a well-designed provider fails predictably and may be able to rely on recently cached data for a short window, while a poorly designed one can cause a full authentication outage.
No — federation is transparent to relying applications. A federated user looks identical to a native Keycloak user from the perspective of any application consuming tokens issued by Keycloak.
Not always — if the legacy system already exposes a standard protocol like LDAP, or has its own full login flow suitable for identity brokering, those existing options may be simpler than building a custom provider from scratch.
Yes — a realm can have multiple User Storage Providers active simultaneously, each handling a different population of users or a different external system, evaluated in a configured priority order.
An already-issued token and active session generally remain valid on their own terms; the impact is mainly felt on new logins or fresh lookups that need to reach the external system, not on sessions already established before the outage began.
14Summary and Key Takeaways
A Custom User Storage Provider is Keycloak’s answer to the very common, very real problem of user data that already exists somewhere else — a legacy database, a proprietary internal system, a directory too risky or too regulated to migrate. Rather than forcing a disruptive, one-time data migration, it lets Keycloak reach out to that external system live, on demand, and present the result as if it were a native user — all while giving every application a single, consistent login experience through Keycloak itself.
Building one well means treating it as genuine authentication-critical infrastructure: implement only the capabilities actually needed, cache thoughtfully rather than not at all, handle the external system’s failures gracefully, and monitor the integration as closely as any other production dependency. Done right, a Custom User Storage Provider becomes the quiet, reliable bridge that lets an organization modernize its authentication layer without ever disturbing the data underneath it.
Key Takeaways
- It’s a live translator, not a migration tool — user data stays in the external system and is queried on demand.
- Built on Keycloak’s User Storage SPI — a documented, plugin-style extension point, not a core modification.
- Capabilities are opt-in — a provider can be strictly read-only, fully read-write, or anywhere in between.
- Caching is a deliberate trade-off — between performance and staying current with the external system.
- Federation is invisible to relying applications — they never need to know a user’s data actually lives elsewhere.
- It’s part of the authentication trust boundary — deserving the same security rigor as any other login-path code.
- Graceful failure handling is essential — an external outage should degrade predictably, not take down login entirely.