I'm using keycloak-spring-security-adapter to secure my application and I have two keycloak realms.
- The "Applications" realm is for single sign on and gets roles from Active Directory
- The "S2S" realm is for system to system communication and gets roles from the "bearer" token in the Authentication header and has keycloak configuration
bearer-only: true
I have two endpoints in my application
/api/clientis secured by the "Applications" realm/s2s/clientis secured by the "S2S" realm
I'm witnessing the following behavior
- In the browser I hit
/s2s/clientand get a 401 unauthorized - In the browser I hit
/api/clientand go through the keycloak redirect for SSO login and ultimately get a 200 response from the rest endpoint - In the browser I hit
/s2s/clientand get a 200 response when I never provided a keycloak token for the S2S realm
I have the following config
security:
keycloak:
adapter-config:
s2s:
realm: S2S
resource: MyClient
auth-server-url: https://my-keycloak.com/auth
ssl-required: none
use-resource-role-mappings: true
public-client: true
bearer-only: true
applications:
realm: Applications
resource: MyClient
auth-server-url: https://my-keycloak.com/auth
ssl-required: none
use-resource-role-mappings: true
public-client: true
And I have the following logic to pick a realm based on the URL which was inspired by the multi tenancy docs
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfiguration {
@Bean
@ConfigurationProperties(prefix = "security.keycloak.adapter-config.s2s")
public AdapterConfig s2sAdapterConfig() {
return new AdapterConfig();
}
@Bean
@ConfigurationProperties(prefix = "security.keycloak.adapter-config.applications")
public AdapterConfig applicationsAdapterConfig() {
return new AdapterConfig();
}
@Bean
public KeycloakConfigResolver keycloakConfigResolver(
@Qualifier("s2sAdapterConfig") AdapterConfig s2sAdapterConfig,
@Qualifier("applicationsAdapterConfig") AdapterConfig applicationsAdapterConfig
) {
KeycloakDeployment s2sDeployment = KeycloakDeploymentBuilder.build(s2sAdapterConfig);
KeycloakDeployment applicationsDeployment = KeycloakDeploymentBuilder.build(applicationsAdapterConfig);
return request -> request.getRelativePath().startsWith("/s2s/") ? s2sDeployment : applicationsDeployment;
}
}
I have the following @KeycloakConfiguration
@KeycloakConfiguration
public static class KeycloakSecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(buildSessionRegistry());
}
@Bean
protected SessionRegistry buildSessionRegistry() {
return new SessionRegistryImpl();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.authorizeRequests()
.antMatchers("/api/**", "/s2s/**").authenticated()
.antMatchers("/actuator/**", "/error").permitAll();
}
}
Version
18.0.2
Expected behavior
Requests to /s2s/* URL's should respond with 401 for all requests that do not have a valid token for the S2S realm
Actual behavior
Requests to /s2s/* URL's receive 200 OK responses when requested with a session cookie that has been authenticated for the Applications realm
How to Reproduce?
- Configure an "Applications" realm in a spring boot application
- Configure a "S2S" realm in the application with
bearer-only: true - Configure the
KeycloakConfigResolverto pick "Applications" realm for\api\*URL's - Configure the
KeycloakConfigResolverto pick "S2S" realm for\s2s\*URL's - Hit an
\api\*URL in the browser and a 200 response (after following keycloak redirects for SSO / cookie) - Hit an
\s2s\*URL in the browser and get a 200 response (should be 401)