This question is about Spring-Security and Multitenancy.
I'm facing a challenge to implement a multitenancy oAuth2-Security for customers who use JWT tokens with realm roles and other without.
So far we have our own Keycloak server and clients have their tokens with realm-roles. This makes it easy to manage which role has access to which endpoint.
Now we will get new clients who need to use their own IDPs and will call some of our endpoints with their own JWT tokens. There are no roles in there and we additionally need to use their user-info or introspection endpoints to indetify the users.
I need help, how to implement such a monster. The one thing is multitenancy - well described in the docs - different issuers... I know. But how can I secure the endpoints - using still the roles for clients who calls them with our tokens (with realm roles) and for the new clients with their own tokens (without roles)?
I see different options:
Multi-tenant OAuth2 clients
With this option, this are the clients which are multi-tenant: it fetch tokens from your authorization server before sending a request to your resource server.
This brings with the best flexibility on user roles: all users and roles assignements are managed in your authorization server. The downside being that each user must be declared in your authorization server and will have to login again before he can access your protected resources (if he doesn't have an active session on your authorization server already).
An option to ease this login on your side it to setup "social login" with their external identity provider ("login with PartnerX" button). It can even be transparent if this partners OAuth2 clients send their authorization request with the
kc_idp_hintparameter (specific to Keycloak, but as this is what you are using ...).When you use the identity providers from above, you could add an "Hardcoded Role" mapper to each of the "Identity Provider" to set a different default role to users from the different identity providers.
Multi-tenant OAuth2 resource server
This solution has the advantage for partners OAuth2 clients to use the token they already have from their own authorization server.
You'll have to provide with your own authentication manager that supports a list of trusted issuers.
An option to have distinct authorities (spring naming for "role") for users from each partner would be to do it in the JWT authentication converter (read the
issclaim and use the host part of this claim or a static mapping or whatever).Unfortunately, what is described in the doc for static multi-tenancy is incompatible with what is described for authorities mapping and you'll have to implement the
AuthenticationManagerResolver<HttpServletRequest>interface yourself (along with a customAuthenticationManagerusing you custom JWT authentication converter).A simple alternative to writing
AuthenticationManagerResolver,AuthenticationManagerandConverter<Jwt, ? extends AbstractAuthenticationToken>yourself is using my starter: