[codex] Route Fed ChatGPT auth through Fed edge (#17151)

## Summary
- parse chatgpt_account_is_fedramp from signed ChatGPT auth metadata
- add _account_is_fedramp=true to ChatGPT backend-api requests only for
FedRAMP ChatGPT-auth accounts
This commit is contained in:
jackz-oai authored and GitHub committed 2026-04-16 07:13:15 +00:00
1 parent 4cd85b28d2
commit f97be7dfff
11 files changed
+103

No files matched your search

+4
View File
@@ -11,6 +11,7 @@ pub fn auth_provider_from_auth(
return Ok(CoreAuthProvider {
token: Some(api_key),
account_id: None,
is_fedramp_account: false,
});
}
@@ -18,6 +19,7 @@ pub fn auth_provider_from_auth(
return Ok(CoreAuthProvider {
token: Some(token),
account_id: None,
is_fedramp_account: false,
});
}
@@ -26,11 +28,13 @@ pub fn auth_provider_from_auth(
Ok(CoreAuthProvider {
token: Some(token),
account_id: auth.get_account_id(),
is_fedramp_account: auth.is_fedramp_account(),
})
} else {
Ok(CoreAuthProvider {
token: None,
account_id: None,
is_fedramp_account: false,
})
}
}
+1
View File
@@ -130,6 +130,7 @@ async fn pro_account_with_no_api_key_uses_chatgpt_auth() {
chatgpt_plan_type: Some(InternalPlanType::Known(InternalKnownPlan::Pro)),
chatgpt_user_id: Some("user-12345".to_string()),
chatgpt_account_id: None,
chatgpt_account_is_fedramp: false,
raw_jwt: fake_jwt,
},
access_token: "test-access-token".to_string(),
+6
View File
@@ -293,6 +293,12 @@ impl CodexAuth {
self.get_current_token_data().and_then(|t| t.account_id)
}
/// Returns false if `is_chatgpt_auth()` is false or the token omits the FedRAMP claim.
pub fn is_fedramp_account(&self) -> bool {
self.get_current_token_data()
.is_some_and(|t| t.id_token.is_fedramp_account())
}
/// Returns `None` if `is_chatgpt_auth()` is false.
pub fn get_account_email(&self) -> Option<String> {
self.get_current_token_data().and_then(|t| t.id_token.email)
+10
View File
@@ -36,6 +36,8 @@ pub struct IdTokenInfo {
pub chatgpt_user_id: Option<String>,
/// Organization/workspace identifier associated with the token, if present.
pub chatgpt_account_id: Option<String>,
/// Whether the selected ChatGPT workspace must route through the FedRAMP edge.
pub chatgpt_account_is_fedramp: bool,
pub raw_jwt: String,
}
@@ -60,6 +62,10 @@ impl IdTokenInfo {
Some(PlanType::Known(plan)) if plan.is_workspace_account()
)
}
pub fn is_fedramp_account(&self) -> bool {
self.chatgpt_account_is_fedramp
}
}
#[derive(Deserialize)]
@@ -88,6 +94,8 @@ struct AuthClaims {
user_id: Option<String>,
#[serde(default)]
chatgpt_account_id: Option<String>,
#[serde(default)]
chatgpt_account_is_fedramp: bool,
}
#[derive(Deserialize)]
@@ -139,6 +147,7 @@ pub fn parse_chatgpt_jwt_claims(jwt: &str) -> Result<IdTokenInfo, IdTokenInfoErr
chatgpt_plan_type: auth.chatgpt_plan_type,
chatgpt_user_id: auth.chatgpt_user_id.or(auth.user_id),
chatgpt_account_id: auth.chatgpt_account_id,
chatgpt_account_is_fedramp: auth.chatgpt_account_is_fedramp,
}),
None => Ok(IdTokenInfo {
email,
@@ -146,6 +155,7 @@ pub fn parse_chatgpt_jwt_claims(jwt: &str) -> Result<IdTokenInfo, IdTokenInfoErr
chatgpt_plan_type: None,
chatgpt_user_id: None,
chatgpt_account_id: None,
chatgpt_account_is_fedramp: false,
}),
}
}
+16
View File
@@ -114,6 +114,22 @@ fn id_token_info_handles_missing_fields() {
let info = parse_chatgpt_jwt_claims(&fake_jwt).expect("should parse");
assert!(info.email.is_none());
assert!(info.get_chatgpt_plan_type().is_none());
assert_eq!(info.is_fedramp_account(), false);
}
#[test]
fn id_token_info_parses_fedramp_account_claim() {
let fake_jwt = fake_jwt(serde_json::json!({
"email": "user@example.com",
"https://api.openai.com/auth": {
"chatgpt_account_id": "account-fed",
"chatgpt_account_is_fedramp": true,
}
}));
let info = parse_chatgpt_jwt_claims(&fake_jwt).expect("should parse");
assert_eq!(info.chatgpt_account_id.as_deref(), Some("account-fed"));
assert_eq!(info.is_fedramp_account(), true);
}
#[test]