feat(auth): configurable runtime-token header (server + SDK) to avoid gateway Authorization collision [HYBIM-741]#253
Draft
josjeon wants to merge 2 commits into
Conversation
josjeon
force-pushed
the
hybim-741-runtime-token-configurable-header
branch
2 times, most recently
from
July 23, 2026 19:42
c771b5d to
163eb58
Compare
…ization collision HYBIM-741. When Agent Control runs behind the O11y gateway, the gateway overwrites `Authorization` with its own downstream identity JWT, clobbering AC's runtime-eval token on the hot path. Make LocalJwtVerifyProvider read the runtime token from a configurable header, selected by AGENT_CONTROL_RUNTIME_TOKEN_HEADER (default `Authorization`). Behind the gateway, point it at a dedicated header (e.g. `X-Agent-Control-Runtime-Token`) so the runtime token and the gateway's Authorization JWT no longer collide. - `Authorization` keeps the mandatory `Bearer` scheme (existing contract). - A dedicated header accepts the raw token (Bearer optional). - Default unchanged: with the env unset, behavior is identical to before. Server-side only; the SDK send-side change is tracked separately. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
josjeon
force-pushed
the
hybim-741-runtime-token-configurable-header
branch
2 times, most recently
from
July 23, 2026 22:15
19dfb5a to
6c4e9c7
Compare
… gateway Authorization collision HYBIM-741. When Agent Control runs behind the O11y gateway, the gateway overwrites `Authorization` with its own downstream identity JWT, clobbering AC's runtime-eval token on the hot path. Make the runtime token ride a configurable header on both sides, selected by AGENT_CONTROL_RUNTIME_TOKEN_HEADER (default `Authorization`): - Server: LocalJwtVerifyProvider reads the token from the configured header; Bearer stays mandatory on Authorization, raw token accepted on a dedicated header. - SDK: AgentControlClient sends the token on the configured header (raw on a dedicated header, Bearer on Authorization) and suppresses the API-key fallback when the runtime token rides its own header, so a runtime request carries a single credential. Default unchanged: with the env unset, behavior is identical to before. Point both sides at a dedicated header (e.g. X-Agent-Control-Runtime-Token) behind the gateway so the runtime token and the gateway Authorization JWT no longer collide. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
josjeon
force-pushed
the
hybim-741-runtime-token-configurable-header
branch
from
July 23, 2026 22:21
6c4e9c7 to
a1d2410
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft yet
Problem
When Agent Control runs behind the O11y gateway, the gateway overwrites
Authorizationwith its own downstream identity JWT — clobbering AC's runtime-eval token on the hot path (HYBIM-741). The runtime token and the gateway's identity JWT both want theAuthorizationheader.Fix
Make the runtime token ride a configurable header on both sides, selected by
AGENT_CONTROL_RUNTIME_TOKEN_HEADER(defaultAuthorization). Behind the gateway, point both sides at a dedicated header (e.g.X-Agent-Control-Runtime-Token); the runtime token rides that header while the gateway keepsAuthorizationfor its identity JWT — no collision.Authorization: keeps the mandatoryBearerscheme (existing contract).Bearerprefix).Server (verify side)
auth_framework/providers/local_jwt.py:LocalJwtVerifyProvidertakes aheader_name(defaultAuthorization) and reads the token from it.Bearerrequired only onAuthorization; raw token accepted on a dedicated header.auth_framework/config.py:_resolve_runtime_token_header()readsAGENT_CONTROL_RUNTIME_TOKEN_HEADER(blank → default), passed into the provider when runtime mode isjwt.SDK (send side)
sdks/python/.../client.py:AgentControlClientgains aruntime_token_headerparam (+ same env var). Sends the runtime token on the configured header — raw on a dedicated header,BeareronAuthorization(single_format_runtime_tokenhelper is the sole authority for that rule). When the runtime token rides its own header, the API-key fallback is suppressed so a runtime request carries a single credential; when no runtime token is minted (e.g.automode + exchange unavailable), the API key still authenticates the request.Configuration (behind the gateway)
Tests
test_auth_framework.py): default Bearer path; default rejects raw onAuthorization; dedicated header reads raw token and coexists with a gatewayAuthorizationJWT; Bearer also accepted on dedicated header; missing-header error names the configured header; blankheader_namerejected; env resolver (unset → default, set → trimmed, whitespace → default).test_client.py): header resolution (param/env/default, blank rejected, whitespace-env fallback); raw token on dedicated header withAuthorizationfree and no API-key ridealong; default sendsBeareronAuthorization; auto-mode fallback keeps the API key when the exchange is unavailable.Security notes
Authorizationis ignored, so it can't be smuggled past the gateway boundary.verify_runtime_token) are unchanged.Notes / scope
noneruntime modes.