mirror of
https://github.com/openai/codex.git
synced 2026-11-05 08:28:29 +00:00
Retry provider auth commands after initial failures (#40523)
## Why A provider auth command can fail during initial credential resolution, leaving no cached authentication. A subsequent `401` should still give the configured provider one bounded opportunity to recover. ## What changed - Treat configured external authentication with an empty cache as eligible for unauthorized recovery. - Allow authority refresh to invoke the external provider when no prior auth is cached, while preserving the existing requirements for managers without an external provider. ## Testing Added unit and client coverage for a provider command that fails initially and succeeds during `401` recovery. GitOrigin-RevId: 7cab9a03f90ce29b412be8fbd97b297acdad4482
This commit is contained in:
1 parent
c1db22a3cd
commit
a7b86b6201
3 files changed
+113
-22
No files matched your search
@@ -745,6 +745,9 @@ impl ProviderAuthCommandFixture {
|
||||
std::fs::write(
|
||||
&script_path,
|
||||
r#"#!/bin/sh
|
||||
if [ -f fail-until-401 ]; then
|
||||
exit 1
|
||||
fi
|
||||
first_line=$(sed -n '1p' tokens.txt)
|
||||
printf '%s\n' "$first_line"
|
||||
tail -n +2 tokens.txt > tokens.next
|
||||
@@ -767,6 +770,7 @@ mv tokens.next tokens.txt
|
||||
&script_path,
|
||||
r#"@echo off
|
||||
setlocal EnableExtensions DisableDelayedExpansion
|
||||
if exist fail-until-401 exit /b 1
|
||||
|
||||
set "first_line="
|
||||
<tokens.txt set /p first_line=
|
||||
@@ -1420,6 +1424,43 @@ async fn provider_auth_command_refreshes_after_401() {
|
||||
send_provider_auth_request(&server, auth_fixture.auth()).await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn provider_auth_command_recovers_after_initial_resolution_failure() {
|
||||
skip_if_no_network!();
|
||||
|
||||
let server = MockServer::start().await;
|
||||
let auth_fixture = ProviderAuthCommandFixture::new(&["recovered-token"]).unwrap();
|
||||
let failure_marker = auth_fixture.tempdir.path().join("fail-until-401");
|
||||
std::fs::write(&failure_marker, "").unwrap();
|
||||
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/v1/responses"))
|
||||
.and(|request: &wiremock::Request| !request.headers.contains_key("authorization"))
|
||||
.respond_with(move |_request: &wiremock::Request| {
|
||||
std::fs::remove_file(&failure_marker).unwrap();
|
||||
ResponseTemplate::new(401).set_body_string("unauthorized")
|
||||
})
|
||||
.expect(1)
|
||||
.mount(&server)
|
||||
.await;
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/v1/responses"))
|
||||
.and(header("authorization", "Bearer recovered-token"))
|
||||
.respond_with(
|
||||
ResponseTemplate::new(200)
|
||||
.insert_header("content-type", "text/event-stream")
|
||||
.set_body_raw(
|
||||
sse(vec![ev_response_created("resp1"), ev_completed("resp1")]),
|
||||
"text/event-stream",
|
||||
),
|
||||
)
|
||||
.expect(1)
|
||||
.mount(&server)
|
||||
.await;
|
||||
|
||||
send_provider_auth_request(&server, auth_fixture.auth()).await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn amazon_bedrock_proxy_uses_command_auth_and_custom_headers() {
|
||||
skip_if_no_network!();
|
||||
|
||||
Reference in new issue
Block a user