feat: load AgentIdentity from JWT login/env#18904
Conversation
db51937 to
f15803b
Compare
ca0aeac to
0d52d99
Compare
There was a problem hiding this comment.
💡 Codex Review
codex/codex-rs/login/src/auth/manager.rs
Lines 1023 to 1030 in ca0aeac
The new JWT/object deserialization for auth.json.agent_identity is ineffective unless auth_mode is also set, because resolved_mode() ignores agent_identity. A JWT-only auth.json falls back to Chatgpt mode and later behaves as missing token auth, which contradicts the “paste one token into auth.json” flow introduced here.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
f15803b to
ae57449
Compare
0d52d99 to
455f6d5
Compare
ec85840 to
d343533
Compare
455f6d5 to
fdfad31
Compare
Disagree here, we should absolutely set |
d343533 to
74c78b4
Compare
fdfad31 to
a87f5e0
Compare
74c78b4 to
ae23fca
Compare
a87f5e0 to
b7a4275
Compare
ae23fca to
bccee32
Compare
b7a4275 to
7bbbecd
Compare
bccee32 to
160793a
Compare
7bbbecd to
c305e9e
Compare
160793a to
df5a2df
Compare
c305e9e to
8afc806
Compare
df5a2df to
ed51cb2
Compare
8afc806 to
f195c46
Compare
| #[serde( | ||
| default, | ||
| skip_serializing_if = "Option::is_none", | ||
| deserialize_with = "deserialize_agent_identity" |
There was a problem hiding this comment.
why are we not storing in a consistent format?
| } | ||
|
|
||
| #[derive(Deserialize)] | ||
| struct AgentIdentityJwtClaims { |
There was a problem hiding this comment.
can this go into agent identity crate?
6a26704 to
1a81344
Compare
6c03831 to
3bb786d
Compare
1a81344 to
466cce8
Compare
3bb786d to
27d0647
Compare
2038a7a to
dc284bd
Compare
aa31e4b to
b0017b5
Compare
c588673 to
c74a2f3
Compare
d339b11 to
ece4453
Compare
## Summary This PR adds `codex-agent-identity` as an isolated crate for Agent Identity business logic. The crate owns: - AgentAssertion construction. - Agent task registration. - private-key assertion signing. - bounded blocking HTTP for task registration. It does not wire AgentIdentity into `auth.json`, `AuthManager`, rollout state, or request callsites. That integration happens in later PRs. Reference old stack: https://github.com/openai/codex/pull/17387/changes ## Stack 1. openai#18757: full revert 2. This PR: isolated Agent Identity crate 3. openai#18785: explicit AgentIdentity auth mode and startup task allocation 4. openai#18811: migrate Codex backend auth callsites through AuthProvider 5. openai#18904: accept AgentIdentity JWTs and load `CODEX_AGENT_IDENTITY` ## Testing Tests: targeted Rust checks, cargo-shear, Bazel lock check, and CI.
## Summary This PR adds `CodexAuth::AgentIdentity` as an explicit auth mode. An AgentIdentity auth record is a standalone `auth.json` mode. When `AuthManager::auth().await` loads that mode, it registers one process-scoped task and stores it in runtime-only state on the auth value. Header creation stays synchronous after that because the task is initialized before callers receive the auth object. This PR also removes the old feature flag path. AgentIdentity is selected by explicit auth mode, not by a hidden flag or lazy mutation of ChatGPT auth records. Reference old stack: https://github.com/openai/codex/pull/17387/changes ## Design Decisions - AgentIdentity is a real auth enum variant because it can be the only credential in `auth.json`. - The process task is ephemeral runtime state. It is not serialized and is not stored in rollout/session data. - Account/user metadata needed by existing Codex backend checks lives on the AgentIdentity record for now. - `is_chatgpt_auth()` remains token-specific. - `uses_codex_backend()` is the broader predicate for ChatGPT-token auth and AgentIdentity auth. ## Stack 1. openai#18757: full revert 2. openai#18871: isolated Agent Identity crate 3. This PR: explicit AgentIdentity auth mode and startup task allocation 4. openai#18811: migrate Codex backend auth callsites through AuthProvider 5. openai#18904: accept AgentIdentity JWTs and load `CODEX_AGENT_IDENTITY` ## Testing Tests: targeted Rust checks, cargo-shear, Bazel lock check, and CI.
213fff4 to
72fe598
Compare
## Summary This PR moves Codex backend request authentication from direct bearer-token handling to `AuthProvider`. The new `codex-auth-provider` crate defines the shared request-auth trait. `CodexAuth::provider()` returns a provider that can apply all headers needed for the selected auth mode. This lets ChatGPT token auth and AgentIdentity auth share the same callsite path: - ChatGPT token auth applies bearer auth plus account/FedRAMP headers where needed. - AgentIdentity auth applies AgentAssertion plus account/FedRAMP headers where needed. Reference old stack: https://github.com/openai/codex/pull/17387/changes ## Callsite Migration | Area | Change | | --- | --- | | backend-client | accepts an `AuthProvider` instead of a raw token/header | | chatgpt client/connectors | applies auth through `CodexAuth::provider()` | | cloud tasks | keeps Codex-backend gating, applies auth through provider | | cloud requirements | uses Codex-backend auth checks and provider headers | | app-server remote control | applies provider headers for backend calls | | MCP Apps/connectors | gates on `uses_codex_backend()` and keys caches from generic account getters | | model refresh | treats AgentIdentity as Codex-backend auth | | OpenAI file upload path | rejects non-Codex-backend auth before applying headers | | core client setup | keeps model-provider auth flow and allows AgentIdentity through provider-backed OpenAI auth | ## Stack 1. #18757: full revert 2. #18871: isolated Agent Identity crate 3. #18785: explicit AgentIdentity auth mode and startup task allocation 4. This PR: migrate Codex backend auth callsites through AuthProvider 5. #18904: accept AgentIdentity JWTs and load `CODEX_AGENT_IDENTITY` ## Testing Tests: targeted Rust checks, cargo-shear, Bazel lock check, and CI.
868e900 to
8d2470f
Compare
8d2470f to
c5d5e7c
Compare
## Summary - decode unsigned agent identity JWT payloads from the web UI format - register agent identity tasks through the production AuthAPI accounts base URL - skip cloud requirement fetches for agent identity auth - improve task registration error details ## Validation - `cargo fmt --check` - `cargo test -p codex-login agent_identity --lib` - `cargo build --bin codex` - local smoke test with `OPENAI_API_KEY` and `CODEX_API_KEY` unset, `CODEX_AGENT_IDENTITY="$CDOEX_TEST_AGENT_IDENTITY"`, and `target/debug/codex exec --skip-git-repo-check --ephemeral "Say exactly: agent identity smoke test ok"` The latest smoke on the squashed commit connected to `wss://chatgpt.com/backend-api/codex/responses` and returned `agent identity smoke test ok`, confirming the agent identity inference path works end to end. Startup side requests for plugins/models/analytics still show 401s under agent identity, but they did not block the inference path.
Summary
This PR lets programmatic AgentIdentity users provide one token through either stdin login or environment auth.
codex login --with-agent-identityreads an Agent Identity JWT from stdin, validates that it has the required claims, and stores that token as theagent_identityvalue inauth.json. The file format is token-only; the decoded account and key fields are runtime state, not hand-authored auth.json fields.The Agent Identity JWT claim shape and decoder live in
codex-agent-identity;codex-loginonly owns env/storage precedence and conversion intoCodexAuth::AgentIdentity.When env auth is enabled,
CODEX_AGENT_IDENTITYcan provide the same JWT without writing auth state to disk.CODEX_API_KEYstill wins if both env vars are set.Reference old stack: https://github.com/openai/codex/pull/17387/changes
Reference JWT/env stack: #18176
Stack
Testing
Tests: targeted login and Agent Identity crate tests, CLI checks, scoped formatter/linter cleanup, and CI.