3

I couldn't find a definitive best practice for this, so I’m hoping the discussion helps others as well.

In a traditional setup (without Keycloak), we keep an application-level User entity with JPA relationships (@OneToMany, @ManyToMany) to domain entities (e.g., Product, Order).
With Keycloak handling authentication and storing user data, what is the production-ready / best-practice way to model users and their relationships?

Option A - Keep a local User table (synced from Keycloak) to maintain JPA relationships, or
Option B - No local users table: store only the Keycloak user ID (sub) in domain entities and avoid a User entity altogether.

Patterns I've seen:
A. Local, synchronized User table

B. No local users table

  • Reference the Keycloak sub directly in domain entities (e.g., Product.ownerSub).

Thank you very much in advance!

2
  • 1
    Identity Providers do provide information about ID (and granted session roles), business users in general tend to have multiple IDs (IRL you may confirm you identity using birth certificate, driver license, passport, student card, etc), so, information provided by IDP somehow relates to the business user but cannot be considered as the only source of truth Commented Nov 1 at 7:34
  • C. Do have a local user table with an internal ID, but only with minimal information in it that need not be synced and the Keycloak userId is stored there as an external ID. You will want to avoid an external ID becoming part of a foreign key which it inevitably will, even if right now it won't. Systems have a tendency to grow in ways you never planned for. Besides, having your own user table grants you the freedom to enable/disable said user in your local system only, rather than the entire keycloak account having to be disabled. Commented Nov 4 at 14:42

3 Answers 3

3

Might be discussed. I think option B is the correct, modern, and production-ready best practice. Your identity provider (Keycloak) should be the single source of truth (SSoT) for user identity. Option A (Syncing) is an anti-pattern. It violates the single source of truth principle. It creates a fragile, tightly-coupled system where your application database is just a stale, partial copy of Keycloak's data.

Sign up to request clarification or add additional context in comments.

Comments

1

Consider referencing users by their Keycloak UUID in your application tables rather than maintaining a separate local user table. If your business requirements don’t demand querying users by name or other attributes locally, storing only the Keycloak UUID allows you to fetch full user details through the Keycloak Admin REST API (GET /realms/{realm}/users/{uuid}) as needed. This approach leverages Keycloak’s built-in IAM security, keeps your app decoupled from identity management concerns, and ensures you always have current data while minimizing local exposure of sensitive user info.

Comments

-1

I do not agree with other answers saying that syncing is not correct. At the time of this writing multi-deployment applications (be they microservices or whatever you want) are a real thing. Often they use separate DBs, so joining data between them is not always an option. These separate deployment/separate DB applications have to synchronize their data and the industry is satisfied with the "eventual consistency" model.

So, in my opinion, syncing is a valid option. Specifically, "Sync via a Keycloak Event Listener SPI on registration/updates". This is a good option because you don't waste CPU/network "cycles" for each request to get potential updates for an infrequently changing piece of data (the user). Not necessarily the correct one, but valid.

If you go for this option, it would be very convenient to use Keycloak's UUID as the key of your private User table, as mentioned in other answers. Make sure to copy only the absolutely minimum set of data your application needs, not more. Certainly not any kind of credentials!!!

This way you have direct, local access to the user information from your application(s), saving you the cost of doing the external call to Keycloak every time you need it and saving Keycloak some resources from replying to the application the same data over and over again. A good caching could protect you from this problem too, if you can sort out the caching invalidation rules.

Speaking of caching, another idea would be to execute the actual call to Keycloak every time you need the user details; but cache the result, so it is only executed once. Use Keycloak's event to invalidate the cache.

I am not sure how are you thinking to implement B? Somehow link the DBs (deploy Keycloak & app in the same DB? Create a link between DB servers? etc). Anyway, I assume a foreign key from your model to Keycloak's. Wouldn't this couple the models a bit too much? Still, it is also valid solution.

Bottom line: in my opinion both are valid. I would choose syncing through Keycloak events, but you should choose whatever fits your needs best.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.