fix(provider): harden Agent Identity OAuth lifecycle

This commit is contained in:
elky
2026-07-23 09:33:00 +08:00
parent e49024d33b
commit 3606290ac8
84 changed files with 8063 additions and 1104 deletions
+55 -8
View File
@@ -85,14 +85,25 @@ impl ProviderKeyAuthSemantics {
pub(crate) fn provider_key_can_refresh_oauth(
auth_semantics: ProviderKeyAuthSemantics,
provider_type: &str,
auth_config: Option<&Map<String, Value>>,
) -> bool {
auth_semantics.can_refresh_oauth()
&& auth_config
.and_then(|config| config.get("refresh_token"))
.and_then(Value::as_str)
.map(str::trim)
.is_some_and(|value| !value.is_empty())
&& (provider_key_auth_config_is_agent_identity(provider_type, auth_config)
|| auth_config
.and_then(|config| config.get("refresh_token"))
.and_then(Value::as_str)
.map(str::trim)
.is_some_and(|value| !value.is_empty()))
}
pub(crate) fn provider_key_can_export_oauth(
auth_semantics: ProviderKeyAuthSemantics,
provider_type: &str,
auth_config: Option<&Map<String, Value>>,
) -> bool {
auth_semantics.can_export_oauth()
&& !provider_key_auth_config_is_agent_identity(provider_type, auth_config)
}
pub(crate) fn provider_key_auth_config_uses_header_authorization(
@@ -291,9 +302,10 @@ mod tests {
use super::{
provider_active_api_formats, provider_key_auth_config_is_agent_identity,
provider_key_auth_config_uses_header_authorization, provider_key_auth_semantics,
provider_key_can_refresh_oauth, provider_key_configured_api_formats,
provider_key_effective_api_formats, provider_key_inherits_provider_api_formats,
ProviderKeyCredentialKind, ProviderKeyRuntimeAuthKind,
provider_key_can_export_oauth, provider_key_can_refresh_oauth,
provider_key_configured_api_formats, provider_key_effective_api_formats,
provider_key_inherits_provider_api_formats, ProviderKeyCredentialKind,
ProviderKeyRuntimeAuthKind,
};
use aether_data_contracts::repository::provider_catalog::{
StoredProviderCatalogEndpoint, StoredProviderCatalogKey,
@@ -396,6 +408,7 @@ mod tests {
assert!(!provider_key_can_refresh_oauth(
semantics,
"codex",
json!({
"access_token": "access-token",
"access_token_import_temporary": true
@@ -404,12 +417,24 @@ mod tests {
));
assert!(!provider_key_can_refresh_oauth(
semantics,
"codex",
json!({ "refresh_token": " " }).as_object()
));
assert!(provider_key_can_refresh_oauth(
semantics,
"codex",
json!({ "refresh_token": "refresh-token" }).as_object()
));
assert!(provider_key_can_refresh_oauth(
semantics,
"codex",
json!({
"auth_mode": "agentIdentity",
"agent_runtime_id": "runtime-1",
"agent_private_key": "private-key-present"
})
.as_object()
));
}
#[test]
@@ -455,6 +480,28 @@ mod tests {
));
}
#[test]
fn agent_identity_is_not_exportable_through_generic_oauth_export() {
let semantics = provider_key_auth_semantics(&sample_key("oauth"), "codex");
let agent_identity = json!({
"auth_mode": "agentIdentity",
"agent_runtime_id": "runtime-1",
"agent_private_key": "base64-private-key",
"task_id": "task-1"
});
assert!(!provider_key_can_export_oauth(
semantics,
"codex",
agent_identity.as_object()
));
assert!(provider_key_can_export_oauth(
semantics,
"codex",
json!({ "refresh_token": "refresh-token" }).as_object()
));
}
#[test]
fn recognizes_legacy_kiro_bearer_key_with_auth_config_as_oauth_managed() {
let mut key = sample_key("bearer");