diff --git a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/PersistenceServiceExternalApiConfiguration.java b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/PersistenceServiceExternalApiConfiguration.java index a8bda5e51..f95d1fd57 100644 --- a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/PersistenceServiceExternalApiConfiguration.java +++ b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/PersistenceServiceExternalApiConfiguration.java @@ -7,6 +7,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import com.fasterxml.jackson.databind.ObjectMapper; import com.iqser.red.persistence.service.v1.external.api.impl.multitenacy.HeaderBasedKeycloakRealmResolver; @Configuration @@ -14,8 +15,8 @@ import com.iqser.red.persistence.service.v1.external.api.impl.multitenacy.Header public class PersistenceServiceExternalApiConfiguration { @Bean - public KeycloakConfigResolver keycloakConfigResolver() { - return new HeaderBasedKeycloakRealmResolver(); + public KeycloakConfigResolver keycloakConfigResolver(ObjectMapper objectMapper) { + return new HeaderBasedKeycloakRealmResolver(objectMapper); } @Autowired diff --git a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/multitenacy/HeaderBasedKeycloakRealmResolver.java b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/multitenacy/HeaderBasedKeycloakRealmResolver.java index 576088edd..a7df36a1f 100644 --- a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/multitenacy/HeaderBasedKeycloakRealmResolver.java +++ b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/multitenacy/HeaderBasedKeycloakRealmResolver.java @@ -2,6 +2,7 @@ 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.Base64; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -13,12 +14,17 @@ import org.keycloak.adapters.OIDCHttpFacade; import org.keycloak.adapters.spi.HttpFacade; import org.keycloak.representations.adapters.config.AdapterConfig; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.iqser.red.service.persistence.management.v1.processor.utils.MagicConverter; +import lombok.RequiredArgsConstructor; import lombok.Setter; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @Slf4j +@RequiredArgsConstructor public class HeaderBasedKeycloakRealmResolver implements KeycloakConfigResolver { private final Map cache = new ConcurrentHashMap<>(); @@ -27,6 +33,7 @@ public class HeaderBasedKeycloakRealmResolver implements KeycloakConfigResolver private static AdapterConfig adapterConfig; private KeycloakDeployment defaultDeployment; + private final ObjectMapper objectMapper; @Override @@ -34,6 +41,11 @@ public class HeaderBasedKeycloakRealmResolver implements KeycloakConfigResolver String tenant = getHeader(request, TENANT_HEADER_NAME); + if (tenant == null) { + // TODO always send as header and remove this. + tenant = getTenantFromBearerToken(request); + } + if (tenant == null) { if (defaultDeployment == null) { defaultDeployment = KeycloakDeploymentBuilder.build(adapterConfig); @@ -45,11 +57,27 @@ public class HeaderBasedKeycloakRealmResolver implements KeycloakConfigResolver } + @SneakyThrows + private String getTenantFromBearerToken(HttpFacade.Request request) { + + String authHeader = request.getHeader("Authorization"); + if (authHeader == null) { + return null; + } + String[] chunks = authHeader.split(" ")[1].split("\\."); + Base64.Decoder decoder = Base64.getUrlDecoder(); + + String payload = new String(decoder.decode(chunks[1])); + JsonNode actualObj = objectMapper.readTree(payload); + String issuer = actualObj.get("iss").asText(); + return issuer.substring(issuer.lastIndexOf('/') + 1); + } + + private KeycloakDeployment createKeyCloakDeployment(String tenant) { var config = MagicConverter.convert(adapterConfig, AdapterConfig.class); config.setRealm(tenant); - config.setResource(tenant); return KeycloakDeploymentBuilder.build(config); } diff --git a/persistence-service-v1/persistence-service-server-v1/src/test/resources/application.yml b/persistence-service-v1/persistence-service-server-v1/src/test/resources/application.yml index 564764660..353ef50fb 100644 --- a/persistence-service-v1/persistence-service-server-v1/src/test/resources/application.yml +++ b/persistence-service-v1/persistence-service-server-v1/src/test/resources/application.yml @@ -119,7 +119,7 @@ keycloak: enabled: true sslRequired: none realm: master - resource: master + resource: redaction disableTrustManager: true useResourceRoleMappings: true