diff --git a/core/network/src/commonMain/kotlin/org/mifospay/core/network/config/InstanceConfigManager.kt b/core/network/src/commonMain/kotlin/org/mifospay/core/network/config/InstanceConfigManager.kt index c3a351ef8..63d5c7ca4 100644 --- a/core/network/src/commonMain/kotlin/org/mifospay/core/network/config/InstanceConfigManager.kt +++ b/core/network/src/commonMain/kotlin/org/mifospay/core/network/config/InstanceConfigManager.kt @@ -19,6 +19,9 @@ class InstanceConfigManager( private val userPreferencesRepository: UserPreferencesRepository, ) : MultiUrlConfigProvider { companion object { + private const val MAX_TENANT_ID_LENGTH = 64 + private val VALID_TENANT_ID_REGEX = Regex("^[A-Za-z0-9_-]+$") + // Default main instance configuration private val DEFAULT_MAIN_INSTANCE = ServerInstance( endpoint = "mifos-bank-2.mifos.community", @@ -68,7 +71,7 @@ class InstanceConfigManager( fun getPath(): String = getCurrentInstance().path - fun getPlatformTenantId(): String = getCurrentInstance().platformTenantId + fun getPlatformTenantId(): String = sanitizeTenantId(getCurrentInstance().platformTenantId) fun getUrl(): String = getCurrentInstance().fullUrl @@ -90,4 +93,18 @@ class InstanceConfigManager( getEndpoint(), getCurrentInterbankInstance().endpoint, ) + + private fun sanitizeTenantId(rawTenantId: String): String { + val normalized = rawTenantId + .trim() + .replace("\r", "") + .replace("\n", "") + .take(MAX_TENANT_ID_LENGTH) + + return if (normalized.isNotEmpty() && VALID_TENANT_ID_REGEX.matches(normalized)) { + normalized + } else { + DEFAULT_MAIN_INSTANCE.platformTenantId + } + } } diff --git a/core/network/src/commonMain/kotlin/org/mifospay/core/network/utils/KtorInterceptor.kt b/core/network/src/commonMain/kotlin/org/mifospay/core/network/utils/KtorInterceptor.kt index 869834276..a8b3d1e79 100644 --- a/core/network/src/commonMain/kotlin/org/mifospay/core/network/utils/KtorInterceptor.kt +++ b/core/network/src/commonMain/kotlin/org/mifospay/core/network/utils/KtorInterceptor.kt @@ -35,8 +35,9 @@ class KtorInterceptor( context.header(BaseURL.HEADER_TENANT, plugin.configManager.getPlatformTenantId()) plugin.getToken()?.let { token -> - if (token.isNotEmpty()) { - context.headers[BaseURL.HEADER_AUTHORIZATION] = "Basic $token" + val sanitizedToken = sanitizeHeaderValue(token) + if (sanitizedToken.isNotEmpty()) { + context.headers[BaseURL.HEADER_AUTHORIZATION] = "Basic $sanitizedToken" } } } @@ -78,8 +79,9 @@ class KtorInterceptorRe( context.header(BaseURL.HEADER_TENANT, plugin.configManager.getPlatformTenantId()) token?.let { token -> - if (token.isNotEmpty()) { - context.headers[BaseURL.HEADER_AUTHORIZATION] = "Basic $token" + val sanitizedToken = sanitizeHeaderValue(token) + if (sanitizedToken.isNotEmpty()) { + context.headers[BaseURL.HEADER_AUTHORIZATION] = "Basic $sanitizedToken" } } } @@ -103,3 +105,10 @@ class ConfigRe { lateinit var repository: UserPreferencesRepository lateinit var configManager: InstanceConfigManager } + +private fun sanitizeHeaderValue(value: String): String { + return value + .trim() + .replace("\r", "") + .replace("\n", "") +}