Keycloak + Multi-tenancy + Spring Security configuration

Hi all,

I’m attempting to use Keycloak to support multi-tenancy within a SpringBoot 2 application using Spring Security.

I’m using



To enable multitenancy I have a MultitenantConfigResolver class which extends KeycloakSpringBootConfigResolver. MultitenantConfigResolver is loaded via my SecurityConfig which extends KeycloakWebSEcurityConfigurerAdapter.

This config resolver largely works as I expect. The target tenant is inferred from the issuer of the provided JWT on the Request. Then an AdapterConfig is built and passed into the;

A key point I’m unsure is correct – when an unauthenticated request is made (no Authorization header), the resolve method of the MultitenantConfigResolver returns null.

I have certain endpoints which I want to be publicly accessible. Those are all prefixed by /public.

In SecurityConfig this is my HttpSecurity configuration:

protected void configure(HttpSecurity http) throws Exception

I’m finding that even when calling an endpoint starting with /public/ my MultitenantConfigResolver is still being called, and the endpoint is not called.

Of a lower priority, in this case instead of returning a 401, I get an empty 200, I’m not sure where to coerce the appropriate status code.

Complete code for both MultitenantConfigResolver and HttpSecurity are here:

Not sure if this is an appropriate fix, but I toyed with returning an empty KeycloakDeployment when no token was provided.

        if (authHeader == null) {
            logger.warn("No Auth header provided");
            return new KeycloakDeployment();

This kept the filter chain from short circuiting but was getting a bad response in Postman. After enabling debug logging, it became clear that Keycloak was attempting to redirect to a /sso/login URL. To avoid this, I set bearerOnly = true on the empty deployment.

        if (authHeader == null) {
            logger.warn("No Auth header provided");
            KeycloakDeployment unConfiguredDeployment = new KeycloakDeployment();
            return unConfiguredDeployment;

This appears to meet my 3 use cases:

  1. Anything in /public/** should be accessible without a token
  2. Anything not in /public should return a 401 without a token
  3. If I have a token, I should be able to process an authenticated endpoint as expected

could you please share the whole code ? Please