We are designing a backend system for a large platform where users can interact with multiple products on behalf of different companies.
We plan to use Keycloak as an external identity provider. The specific implementation doesn’t matter, as it may change in the future; the important point is that there will always be an external identity provider involved.
This is, of course, a challenging task, and I would like to share some of the doubts we have. Any insight or suggestions would be greatly appreciated.
1. User Data Distribution Across the System
Our current plan is to store only the essential user data in the identity provider (for example, email and password) and keep everything else (such as profile picture, first name, preferences, and even a copy of the email) in our database.
The main reason for this is to simplify querying the user base without having to rely on the identity provider (which, in Keycloak, is not well supported).
Since we will also have a complex RBAC model, we are considering storing roles and the relationships between users, products, and companies in our own database as well.
This seems like the most reasonable approach, but are there potential issues we might encounter that would be avoided by a different approach (e.g. storing most of the data inside the identity provider)
2. User Claims
Because we plan to store roles, billing plans, and similar information in our database, another important question is how to handle user claims.
A user may have different roles for each combination of company and product. We have considered two approaches:
Option 1: Store Claims in the JWT
This seems like a clean and lightweight approach, as the JWT would include all the claims needed for authentication and authorization.
The challenge is how to issue this token.
The identity provider would need to know the user’s state in our system. One possible solution is to have an independent authorization server that returns the user’s roles for each specific product and company, which the identity provider would call whenever a user authenticates.
Option 2: Issue a Minimal JWT and Fetch Permissions Later
Alternatively, we could issue a minimal JWT and let each part of the infrastructure fetch permissions as needed.
This is simpler to implement at first but adds complexity in the long run, as every component would depend on the authorization server. Caching mechanisms would likely be necessary to prevent overwhelming it with requests.
——
Given these constraints, and given the possible solutions, what do you think we need to consider in order to achieve our goal?
