fix(auth): bind JWT trust by issuer - #19
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The external principal-source validation does not currently reserve internal principal-source names in the external:<slug> namespace, which conflicts with the PR’s stated constraint and should be enforced before merge.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR introduces issuer-scoped JWT trust configuration for the librechat-jwt auth provider, so an unverified iss claim can only select a predefined verification policy (keys, algorithms, audiences, and principal sources) before any principal is accepted, while preserving the legacy single-issuer LibreChat behavior when the modern trust table is not configured.
Changes:
- Add
CODEAPI_JWT_TRUST_ENTRIES_JSONsupport with strict parsing/validation and per-issuer binding ofkid,alg, audience, andprincipal_source. - Expand auth tests to cover modern multi-issuer mode, config failure cases, and cache reload behavior.
- Document the new configuration in Helm/Docker Compose and record the fork patch behavior.
File summaries
| File | Description |
|---|---|
| service/src/auth/librechat-jwt.ts | Implements issuer-keyed trust entries, key ID uniqueness checks, and issuer-bound verification/claim validation. |
| service/src/auth/librechat-jwt.test.ts | Adds focused tests for modern trust-table behavior, rejection cases, and reload semantics. |
| helm/codeapi/README.md | Documents how to configure CODEAPI_JWT_TRUST_ENTRIES_JSON and issuer-scoped constraints. |
| docs/fork/patches.md | Records the new fork behavior and its owned/shared paths and drop criteria. |
| docker-compose.yaml | Exposes CODEAPI_JWT_TRUST_ENTRIES_JSON for local/container configuration. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| 'openid_reuse', | ||
| ]); | ||
| const EXTERNAL_PRINCIPAL_SOURCE = /^external:([a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?)$/; | ||
| const RESERVED_EXTERNAL_SOURCE_SLUGS = new Set(['synthetic_test', 'none', 'api_key']); |
What This Fixes
This PR adds one reusable issuer-scoped JWT trust boundary:
issuer, audience, and principal source before accepting a principal.
trust table is set.
external:<slug>namespacewithout embedding a consumer-specific source.
This is an independent draft package extracted from PR #18. It has no source
dependency on the logging or public-contract packages.
How It Works
CODEAPI_JWT_TRUST_ENTRIES_JSONdefines modern issuer entries with acceptedaudiences, key IDs, algorithms, and principal sources.
issclaim only selects a trust entry. Its assigned key and allconfigured constraints are enforced before claims become a principal.
and each external source belongs to exactly one entry.
external:<slug>values. Reserved internalvalues cannot be configured through that namespace.
<principal-source>:<tenant-id>. Internal tenantIDs remain unchanged.
Important Details
orphaned, cross-entry, or algorithm-incompatible configuration fails startup.
database schema, or rate-limit change.
docs/fork/patches.mdrecords the eighth active UZH fork behavior and itsreplay/drop condition.
included.
Branch Coverage
main@83c4f7b40cde7d83c4f7b..40cde7d, 5 commits.or project-plan delta.
documentation, fork ledger, simplifier cleanup, and review corrections.
Review Focus
principal-source trust.
remains equivalent.
external:<slug>validation and tenant namespace derivation preventcross-issuer storage/session collisions.
Verification
Current head:
bun test src/auth/librechat-jwt.test.tsfromservice/-> 21 pass, 0 fail.bun run testfromservice/-> 559 pass, 0 fail.bun run buildfromservice/-> exit 0.git diff --check origin/main...HEAD-> pass.-> all five required jobs passed at
40cde7d.Failed/Warning:
and two pre-existing TS2352 warnings outside this package.
Not run:
authentication proof was used. Those remain separate rollout actions.
Security / Privacy
review.
40cde7d.credentials, personal data, production token, or execution payload is
included.
Blocking Before Merge
Follow-Up After Merge
deployment change.
package is present on an exact UZH
mainSHA.Local Session Artifacts
Machine-local pointers for a session resuming this branch, not review evidence.
Rolands-Mac-Studio.localtrees/codeapi-trust-contract-loggingin repositorycode-interpreter~/Git/klicker/klicker-uzh/trees/rs-codeapi-upstream-simplification/project/2026-08-31-codeapi-source-simplification-plan.md