feat(auth): explicitly type sandbox JWTs with a compatible migration
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 8.7k
- Forks
- 1.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 253
Description
Problem Statement
Sandbox admission JWTs currently use the generic JWT JOSE type (or may be untyped), while extension credentials use openshell-ext+jwt. PR #2638 prevents cross-domain replay by rejecting extension-token types at the sandbox authentication boundary and reserving the gateway sandbox audience, but sandbox credentials still lack their own explicit type.
An explicit sandbox token type adds defense in depth and enables the gateway to validate the sandbox trust domain independently of claims. Strict enforcement cannot be enabled immediately because supervisors may retain legacy tokens across a gateway upgrade, and sandbox JWTs may be configured as non-expiring.
Proposed Design
Introduce openshell-sandbox+jwt for gateway-minted sandbox admission tokens.
Phase 1 — compatible rollout:
- Define the sandbox token type in the gateway sandbox-authentication module rather than
openshell-extension-core. - Set
typ: openshell-sandbox+jwton every newly minted sandbox JWT. - Accept
openshell-sandbox+jwt, legacyJWT, and missingtypduring validation. - Continue to reject
openshell-ext+jwtunconditionally, as implemented by #2638. - Add tests for the new minting header, new-token authentication, legacy
JWTauthentication, untyped-token authentication, and extension-token rejection. - Document the compatibility window and expose enough diagnostics to determine whether legacy tokens are still presented.
Phase 2 — strict validation:
- Require
typ: openshell-sandbox+jwtexactly. - Remove legacy
JWTand untyped acceptance only after a defined cutover mechanism guarantees old credentials have been replaced. Token TTL alone is insufficient becausegateway_jwt.ttl_secs = 0permits non-expiring credentials. - Use either an explicit compatibility setting/deprecation cycle or a restart/refresh mechanism that reissues credentials for all active sandboxes before strict mode becomes the default.
Alternatives Considered
- Keep rejecting only
openshell-ext+jwt: this closes the known replay path but leaves sandbox credentials without a positive trust-domain discriminator. - Enforce the new type immediately: simpler validation, but it can break running supervisors holding tokens minted before a gateway upgrade.
- Put the constant in
openshell-extension-core: rejected because sandbox admission is gateway-internal authentication, not extension-facing functionality. - Use a separate signing key immediately: stronger trust-domain separation, but substantially broader than token typing and can remain a later key-rotation design.
Agent Investigation
Related work: #2623 and PR #2638.
SandboxJwtIssuer::mint currently constructs a generic EdDSA header and sets only kid; jsonwebtoken::Header::new supplies the legacy JWT type. SandboxJwtAuthenticator::validate_bearer now rejects openshell-ext+jwt before key fallback but otherwise accepts the legacy header shape. The gateway is both issuer and validator, while supervisors transport and may cache the opaque credential, making additive minting safe but immediate strict validation unsafe across rolling upgrades.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with SandboxJwtIssuer::mint and SandboxJwtAuthenticator::validate_bearer in the gateway sandbox-authentication module, then inspect the tests and related work in #2623 and PR #2638. Implement the compatible Phase 1 behavior: mint the sandbox type, accept new, legacy, and untyped tokens, reject extension tokens, and cover each case with tests. Document the compatibility window and provide diagnostics for legacy-token use.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- authentication, backend, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100