RED-4515: Intercept keycloak authentication and choose realm from tenant header
This commit is contained in:
parent
112a27561b
commit
be364e2c6d
@ -43,8 +43,10 @@ import lombok.RequiredArgsConstructor;
|
||||
@EnableConfigurationProperties(KeyCloakSettings.class)
|
||||
@Import(KeycloakSpringBootConfigResolver.class)
|
||||
public class SecuredKeyCloakConfiguration extends KeycloakWebSecurityConfigurerAdapter {
|
||||
|
||||
private final KeyCloakSettings keyCloakSettings;
|
||||
|
||||
|
||||
@Bean
|
||||
public KeycloakBaseSpringBootConfiguration keycloakBaseSpringBootConfiguration() {
|
||||
|
||||
@ -67,12 +69,13 @@ public class SecuredKeyCloakConfiguration extends KeycloakWebSecurityConfigurerA
|
||||
@Override
|
||||
public void configure(WebSecurity web) {
|
||||
|
||||
web.ignoring().antMatchers("/actuator/health/**",
|
||||
"/redaction-gateway-v1/async/download/with-ott/**",
|
||||
"/redaction-gateway-v1/docs/**",
|
||||
"/redaction-gateway-v1/docs",
|
||||
"/redaction-gateway-v1",
|
||||
"/internal-api/**");
|
||||
web.ignoring()
|
||||
.antMatchers("/actuator/health/**",
|
||||
"/redaction-gateway-v1/async/download/with-ott/**",
|
||||
"/redaction-gateway-v1/docs/**",
|
||||
"/redaction-gateway-v1/docs",
|
||||
"/redaction-gateway-v1",
|
||||
"/internal-api/**");
|
||||
|
||||
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
|
||||
}
|
||||
@ -84,6 +87,7 @@ public class SecuredKeyCloakConfiguration extends KeycloakWebSecurityConfigurerA
|
||||
protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
|
||||
|
||||
KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(authenticationManagerBean());
|
||||
|
||||
filter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy());
|
||||
filter.setRequestAuthenticatorFactory(new SpringSecurityRequestAuthenticatorFactory() {
|
||||
|
||||
@ -142,6 +146,4 @@ public class SecuredKeyCloakConfiguration extends KeycloakWebSecurityConfigurerA
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,11 +1,26 @@
|
||||
package com.iqser.red.persistence.service.v1.external.api.impl;
|
||||
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
import org.keycloak.adapters.springboot.KeycloakSpringBootProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.iqser.red.persistence.service.v1.external.api.impl.multitenacy.HeaderBasedKeycloakRealmResolver;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
public class PersistenceServiceExternalApiConfiguration {
|
||||
|
||||
@Bean
|
||||
public KeycloakConfigResolver keycloakConfigResolver() {
|
||||
return new HeaderBasedKeycloakRealmResolver();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setKeycloakSpringBootProperties(final KeycloakSpringBootProperties keycloakProperties) {
|
||||
HeaderBasedKeycloakRealmResolver.setAdapterConfig(keycloakProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
package com.iqser.red.persistence.service.v1.external.api.impl.multitenacy;
|
||||
|
||||
import static com.iqser.red.service.persistence.management.v1.processor.multitenancy.TenantInterceptor.TENANT_HEADER_NAME;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
|
||||
import com.iqser.red.service.persistence.management.v1.processor.utils.MagicConverter;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class HeaderBasedKeycloakRealmResolver implements KeycloakConfigResolver {
|
||||
|
||||
private final Map<String, KeycloakDeployment> cache = new ConcurrentHashMap<>();
|
||||
|
||||
@Setter
|
||||
private static AdapterConfig adapterConfig;
|
||||
|
||||
private KeycloakDeployment defaultDeployment;
|
||||
|
||||
|
||||
@Override
|
||||
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
|
||||
|
||||
String tenant = getHeader(request, TENANT_HEADER_NAME);
|
||||
|
||||
if (tenant == null) {
|
||||
if (defaultDeployment == null) {
|
||||
defaultDeployment = KeycloakDeploymentBuilder.build(adapterConfig);
|
||||
}
|
||||
return defaultDeployment;
|
||||
}
|
||||
|
||||
return cache.computeIfAbsent(tenant, this::createKeyCloakDeployment);
|
||||
}
|
||||
|
||||
|
||||
private KeycloakDeployment createKeyCloakDeployment(String tenant) {
|
||||
|
||||
var config = MagicConverter.convert(adapterConfig, AdapterConfig.class);
|
||||
config.setRealm(tenant);
|
||||
|
||||
return KeycloakDeploymentBuilder.build(config);
|
||||
}
|
||||
|
||||
|
||||
private String getHeader(HttpFacade.Request request, String headerName) {
|
||||
|
||||
List<String> values = request.getHeaders(headerName);
|
||||
if (values == null || values.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return values.get(values.size() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user