Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KTOR-7644 Make re-auth status codes configurable #4420

Open
wants to merge 4 commits into
base: 3.1.0-eap
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
public final class io/ktor/client/plugins/auth/AuthConfig {
public fun <init> ()V
public final fun getProviders ()Ljava/util/List;
public final fun getReAuthStatusCodes ()Ljava/util/List;
}

public final class io/ktor/client/plugins/auth/AuthKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ final class io.ktor.client.plugins.auth/AuthConfig { // io.ktor.client.plugins.a

final val providers // io.ktor.client.plugins.auth/AuthConfig.providers|{}providers[0]
final fun <get-providers>(): kotlin.collections/MutableList<io.ktor.client.plugins.auth/AuthProvider> // io.ktor.client.plugins.auth/AuthConfig.providers.<get-providers>|<get-providers>(){}[0]
final val reAuthStatusCodes // io.ktor.client.plugins.auth/AuthConfig.reAuthStatusCodes|{}reAuthStatusCodes[0]
final fun <get-reAuthStatusCodes>(): kotlin.collections/MutableList<io.ktor.http/HttpStatusCode> // io.ktor.client.plugins.auth/AuthConfig.reAuthStatusCodes.<get-reAuthStatusCodes>|<get-reAuthStatusCodes>(){}[0]
}

final val io.ktor.client.plugins.auth/Auth // io.ktor.client.plugins.auth/Auth|{}Auth[0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ private class AtomicCounter {
@KtorDsl
public class AuthConfig {
public val providers: MutableList<AuthProvider> = mutableListOf()
public val reAuthStatusCodes: MutableList<HttpStatusCode> = mutableListOf(HttpStatusCode.Unauthorized)
}

/**
Expand All @@ -40,6 +41,7 @@ public val AuthCircuitBreaker: AttributeKey<Unit> = AttributeKey("auth-request")
* You can learn more from [Authentication and authorization](https://ktor.io/docs/auth.html).
*
* [providers] - list of auth providers to use.
* [reAuthStatusCodes] - list of [HttpStatusCode] values which trigger a re-auth.
*/
public val Auth: ClientPlugin<AuthConfig> = createClientPlugin("Auth", ::AuthConfig) {
val providers = pluginConfig.providers.toList()
Expand Down Expand Up @@ -128,14 +130,14 @@ public val Auth: ClientPlugin<AuthConfig> = createClientPlugin("Auth", ::AuthCon

on(Send) { originalRequest ->
val origin = proceed(originalRequest)
if (origin.response.status != HttpStatusCode.Unauthorized) return@on origin
if (origin.response.status !in pluginConfig.reAuthStatusCodes) return@on origin
if (origin.request.attributes.contains(AuthCircuitBreaker)) return@on origin

var call = origin

val candidateProviders = HashSet(providers)

while (call.response.status == HttpStatusCode.Unauthorized) {
while (call.response.status in pluginConfig.reAuthStatusCodes) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Speaking of broken services, I've seen some APIs returning 200 OK with actual status code in a body. We could provide a lambda instead of a list of statuses:

var isUnauthorized: (HttpResponse) -> Boolean = { it.status == HttpStatusCode.Unauthorized }

@e5l, @bjhham, @marychatte, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds much better than the list. I've pushed that change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@osipxd
I like the idea with lambda!

returning 200 OK with actual status code in a body

Do you mean it could be used like this?
isUnauthorized = { it.bodyAsText() == "401" }
If yes, then isUnauthorized function should be suspend

LOGGER.trace("Received 401 for ${call.request.url}")
osipxd marked this conversation as resolved.
Show resolved Hide resolved

val (provider, authHeader) = findProvider(call, candidateProviders) ?: run {
Expand Down