'KTOR Client and Spring Switchuser
I'm trying to implement a client for spring-security's SwitchUserFilter
(server-side). As client I'm using KTOR (with OKHttp inside).
SwitchUserFilter
requires me to log in, then drop the Authorization
header and use the Cookie
tinstead. If I send the Authorization
header together with the Cookie
header, spring's SecurityContext coming from SwitchUserFilter
will be overwritten with my admin user again.
Is there something I can configure in KTOR, so that the [Authorization] header is removed, once I have switched the user?
Solution 1:[1]
KTOR has to be setup with two things:
SwitchUserFilter will send a redirect (HTTP 302) that we need to ignore. For this a HttpResponseValidator needs to be configured.
Auth needs to be removed similar to the comment from @Delta_George
HttpClient(OkHttp) { HttpResponseValidator { // for 302 don't react - so we can switch user successfully. If we follow, this doesn't work anymore. validateResponse { response -> val statusCode = response.status.value val originCall = response.call if (statusCode < 300 || originCall.attributes.contains(ValidateMark)) { return@validateResponse } val exceptionCall = originCall.save().apply { attributes.put(ValidateMark, Unit) } val excResp = exceptionCall.response val excRespTxt = excResp.readText() when (statusCode) { 302 -> {} // do nothing on "Found" statuscode in 300..399 -> throw RedirectResponseException(excResp, excRespTxt) in 400..499 -> throw ClientRequestException(excResp, excRespTxt) in 500..599 -> throw ServerResponseException(excResp, excRespTxt) else -> throw ResponseException(excResp, excRespTxt) } } } ... // other configurations }
and impersonate(...)
:
suspend fun impersonate(impersonateWithUser: PersonEntity): Impersonation<PersonEntity> {
return runCatching {
val toImpersonate = impersonateWithUser.login.replace(Regex("^\\+"), "%2B")
client.get<HttpResponse>("$BASE_URL/login/impersonate?username=${toImpersonate}") // with baseauth again
}.map {
when (it.status) {
HttpStatusCode.Found -> {
client.feature(Auth)!!.providers.removeAll { true }
Impersonation.ok(impersonateWithUser)
}
else -> Impersonation.failure(impersonateWithUser, it)
}
}.getOrElse {
Log.e(TAG, "impersonate: ", it)
Impersonation.communicationError(impersonateWithUser, it)
}
}
to end the impersonation you call the respective endpoint given in SwitchUserFilter on the serverside.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Frischling |