fix(02-04): harden Android OIDC token result mapping
- Treat missing access tokens as auth failures - Preserve AppAuth discovery errors for correct network/auth classification
This commit is contained in:
@@ -28,8 +28,11 @@ actual class OidcClient {
|
||||
get() = GlobalContext.get().get<Context>().applicationContext
|
||||
|
||||
actual suspend fun login(): OidcResult {
|
||||
val configuration = fetchConfiguration()
|
||||
?: return OidcResult.NetworkError
|
||||
val configuration =
|
||||
when (val outcome = fetchConfiguration()) {
|
||||
is ConfigurationOutcome.Success -> outcome.configuration
|
||||
is ConfigurationOutcome.Error -> return outcome.exception.toOidcError()
|
||||
}
|
||||
|
||||
val request =
|
||||
AuthorizationRequest
|
||||
@@ -87,14 +90,19 @@ actual class OidcClient {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchConfiguration(): AuthorizationServiceConfiguration? =
|
||||
private suspend fun fetchConfiguration(): ConfigurationOutcome =
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
AuthorizationServiceConfiguration.fetchFromIssuer(Uri.parse(Constants.OIDC_ISSUER)) { configuration, exception ->
|
||||
if (!continuation.isActive) return@fetchFromIssuer
|
||||
when {
|
||||
configuration != null -> continuation.resume(configuration)
|
||||
exception != null && exception.isNetworkFailure() -> continuation.resume(null)
|
||||
else -> continuation.resume(null)
|
||||
configuration != null -> continuation.resume(ConfigurationOutcome.Success(configuration))
|
||||
exception != null -> continuation.resume(ConfigurationOutcome.Error(exception))
|
||||
else ->
|
||||
continuation.resume(
|
||||
ConfigurationOutcome.Error(
|
||||
AuthorizationException.GeneralErrors.INVALID_DISCOVERY_DOCUMENT,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,6 +118,8 @@ actual class OidcClient {
|
||||
when {
|
||||
exception != null -> continuation.resume(exception.toOidcError())
|
||||
tokenResponse == null -> continuation.resume(OidcResult.AuthError("Token exchange returned no response"))
|
||||
tokenResponse.accessToken.isNullOrBlank() ->
|
||||
continuation.resume(OidcResult.AuthError("Token exchange returned no access token"))
|
||||
else -> {
|
||||
authState.update(tokenResponse, null)
|
||||
continuation.resume(authState.toSuccess(tokenResponse))
|
||||
@@ -276,4 +286,10 @@ actual class OidcClient {
|
||||
|
||||
data object Cancelled : AuthorizationOutcome
|
||||
}
|
||||
|
||||
private sealed interface ConfigurationOutcome {
|
||||
data class Success(val configuration: AuthorizationServiceConfiguration) : ConfigurationOutcome
|
||||
|
||||
data class Error(val exception: AuthorizationException) : ConfigurationOutcome
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user