mirror of
https://github.com/openai/codex.git
synced 2026-10-30 19:18:49 +00:00
## What changed Allow omitting `gateway_oauth.delivery` to send the gateway token as `Authorization: Bearer …`. Custom headers and cookies remain available when a provider also needs its own credentials. Reject conflicting provider authentication and duplicate delivery headers with actionable errors. For gateway bearer delivery, require `model_catalog_url` to share the scheme, host, and port of `base_url`. Consistently reject request header collisions across auth application methods. ## Testing Add coverage for omitted delivery, provider credential conflicts, and model catalog origin validation. Update inference tests to verify gateway-only authentication while signed in and combined ChatGPT and gateway credentials in separate headers. GitOrigin-RevId: 8564d3998511b3f6c55f3b65a01ed9056a90417e
121 lines
3.8 KiB
Rust
121 lines
3.8 KiB
Rust
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
fn provider(extra: &str) -> ModelProviderInfo {
|
|
toml::from_str(&format!(
|
|
r#"
|
|
base_url = "https://gateway.example.test/v1"
|
|
[gateway_oauth]
|
|
authorization_url = "https://login.example.test/authorize"
|
|
token_url = "https://login.example.test/token"
|
|
client_id = "codex"
|
|
{extra}
|
|
"#
|
|
))
|
|
.unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn parses_header_and_cookie_delivery() {
|
|
let header = provider("delivery = { kind = 'header', name = 'x-gateway-auth' }");
|
|
assert_eq!(header.validate(), Ok(()));
|
|
assert_eq!(
|
|
header.gateway_oauth.as_ref().unwrap().delivery,
|
|
GatewayOAuthDelivery::Header {
|
|
name: "x-gateway-auth".into(),
|
|
scheme: "Bearer".into(),
|
|
}
|
|
);
|
|
let cookie = provider("delivery = { kind = 'cookie', name = 'gateway_session' }");
|
|
assert_eq!(cookie.validate(), Ok(()));
|
|
assert_eq!(
|
|
toml::from_str::<ModelProviderInfo>(&toml::to_string(&cookie).unwrap()).unwrap(),
|
|
cookie
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_unsafe_endpoints_and_delivery_collisions() {
|
|
let valid = provider("delivery = { kind = 'header', name = 'x-gateway-auth' }");
|
|
for url in [
|
|
"http://remote.example.test",
|
|
"https://user:secret@gateway.example.test",
|
|
"https://gateway.example.test/#secret",
|
|
"file:///token",
|
|
] {
|
|
let mut invalid = valid.clone();
|
|
invalid.base_url = Some(url.into());
|
|
assert!(invalid.validate().is_err());
|
|
invalid = valid.clone();
|
|
invalid.gateway_oauth.as_mut().unwrap().token_url = url.into();
|
|
let error = invalid.validate().unwrap_err();
|
|
assert!(!error.contains(url));
|
|
}
|
|
for name in [
|
|
"HOST",
|
|
"x-openai-actor-authorization",
|
|
"content-length",
|
|
"sec-websocket-key",
|
|
"bad name",
|
|
] {
|
|
let invalid = provider(&format!(
|
|
"delivery = {{ kind = 'header', name = '{name}' }}"
|
|
));
|
|
assert!(invalid.validate().is_err(), "{name}");
|
|
}
|
|
let mut collision = valid;
|
|
collision.http_headers = Some(std::collections::HashMap::from([(
|
|
"X-Gateway-Auth".into(),
|
|
"static".into(),
|
|
)]));
|
|
assert!(collision.validate().is_err());
|
|
let mut cookie = provider("delivery = { kind = 'cookie', name = 'gateway' }");
|
|
cookie.env_http_headers = Some(std::collections::HashMap::from([(
|
|
"COOKIE".into(),
|
|
"COOKIE_ENV".into(),
|
|
)]));
|
|
assert!(cookie.validate().is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn gateway_bearer_requires_the_model_catalog_to_share_its_origin() {
|
|
let other = "https://gateway.example.test:8443/catalog";
|
|
let mut info = provider("");
|
|
info.model_catalog_url = Some(other.into());
|
|
assert!(
|
|
info.validate()
|
|
.unwrap_err()
|
|
.contains("same scheme, host, and port as base_url")
|
|
);
|
|
|
|
info.model_catalog_url = Some("https://gateway.example.test:443/custom/catalog".into());
|
|
assert_eq!(info.validate(), Ok(()));
|
|
|
|
let mut legacy = provider("delivery = { kind = 'header', name = 'x-gateway-auth' }");
|
|
legacy.model_catalog_url = Some(other.into());
|
|
assert_eq!(legacy.validate(), Ok(()));
|
|
}
|
|
|
|
#[test]
|
|
fn omitted_delivery_rejects_an_existing_provider_bearer() {
|
|
let mut info = provider("");
|
|
assert_eq!(info.validate(), Ok(()));
|
|
info.requires_openai_auth = true;
|
|
assert!(
|
|
info.validate()
|
|
.unwrap_err()
|
|
.contains("gateway_oauth.delivery")
|
|
);
|
|
info.requires_openai_auth = false;
|
|
info.env_key = Some("PROVIDER_API_KEY".into());
|
|
assert!(
|
|
info.validate()
|
|
.unwrap_err()
|
|
.contains("gateway_oauth.delivery")
|
|
);
|
|
|
|
let mut explicit = provider("delivery = { kind = 'header', name = 'x-gateway-auth' }");
|
|
explicit.env_key = info.env_key;
|
|
assert_eq!(explicit.validate(), Ok(()));
|
|
}
|