feat(core): improve auth handling (#15271)

fix #15270
fix #15260
fix #15257


#### PR Dependency Tree


* **PR #15271** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
This commit is contained in:
DarkSky
2026-07-18 06:27:01 +08:00
committed by GitHub
parent 427db39862
commit d24c17f300
17 changed files with 273 additions and 99 deletions
@@ -56,7 +56,20 @@ private data class TokenPair(
val json: String,
)
private class AuthServerException(val code: String?, val status: Int) : Exception(code)
private class AuthServerException(
val code: String?,
val status: Int,
override val message: String,
) : Exception(message)
private fun authServerException(status: Int, text: String): AuthServerException {
val body = runCatching { JSONObject(text) }.getOrNull()
val code = body?.optString("code")?.takeIf { it.isNotEmpty() }
?: body?.optString("name")?.takeIf { it.isNotEmpty() }
val message = body?.optString("message")?.takeIf { it.isNotEmpty() }
?: "Authentication request failed with status $status"
return AuthServerException(code, status, message)
}
private val permanentAuthErrors = setOf(
"ACCESS_TOKEN_INVALID", "AUTH_SESSION_EXPIRED", "AUTH_SESSION_REVOKED",
@@ -183,8 +196,7 @@ internal class AuthSessionBroker(
AuthHttp.client.newCall(request).executeAsync().use { response ->
val text = response.body.string()
if (response.code < 400) return text
val code = runCatching { JSONObject(text).optString("code").ifEmpty { null } }.getOrNull()
val error = AuthServerException(code, response.code)
val error = authServerException(response.code, text)
if (response.code < 500 || attempt == 2) throw error
last = error
}
@@ -338,7 +350,7 @@ class AuthPlugin : Plugin() {
.build()
val exchangeCode = AuthHttp.client.newCall(request).executeAsync().use { response ->
val text = response.body.string()
if (response.code >= 400) throw IllegalStateException(text)
if (response.code >= 400) throw authServerException(response.code, text)
JSONObject(text).getString("exchangeCode")
}
val exchangeBody = JSONObject()
@@ -353,7 +365,7 @@ class AuthPlugin : Plugin() {
.build()
val tokenResponse = AuthHttp.client.newCall(exchangeRequest).executeAsync().use { response ->
val text = response.body.string()
if (response.code >= 400) throw IllegalStateException(text)
if (response.code >= 400) throw authServerException(response.code, text)
text
}
broker.store(endpoint, tokenResponse)
@@ -385,7 +397,8 @@ class AuthPlugin : Plugin() {
?: "AUTH_SESSION_TEMPORARILY_UNAVAILABLE"
else -> "AUTH_SESSION_TEMPORARILY_UNAVAILABLE"
}
call.reject("Auth operation failed", code, error)
val message = if (error is AuthServerException) error.message else "Auth operation failed"
call.reject(message, code, error)
}
}
}