8000 feat: add the id-jag assertion validation chain by avelino · Pull Request #134 · avelino/mcp · GitHub
[go: up one dir, main page]

Skip to content

feat: add the id-jag assertion validation chain - #134

Merged
avelino merged 3 commits into
mainfrom
feat/enterprise-managed-auth
Nov 4, 2026
Merged

avelino merged 3 commits into
mainfrom
feat/enterprise-managed-auth

Conversation

@avelino
@avelino avelino commented Nov 4, 2026
Copy link
Copy Markdown
Owner

Claude.ai only reaches this server through DCR plus authorization_code, so every user sits through a consent screen. Enterprise-managed auth replaces that with a signed identity assertion that the organization's issuer exchanges at /token, and none of the machinery to validate one existed.

Validation comes first: the nine ordered checks the EMA extension defines, a per-issuer JWKS cache with its own timeout budget, replay protection keyed on (issuer, jti), trustedIssuers and staticClients in config, and the WWW-Authenticate challenge on 401. Roles come from config, never from the assertion. The jwt-bearer arm of /token is not here yet, so no production path changes.

Workflows also get concurrency: a new push cancels the branch's older builds, while publish and deploy serialize instead of cancelling.

Claude.ai only reaches this server through DCR plus authorization_code,
so every user sits through a consent screen. Enterprise-managed auth
replaces that with a signed identity assertion that the organization's
issuer exchanges at /token, and none of the machinery to validate one
existed.

Validation comes first: the nine ordered checks the EMA extension
defines, a per-issuer JWKS cache with its own timeout budget, replay
protection keyed on (issuer, jti), trustedIssuers and staticClients in
config, and the WWW-Authenticate challenge on 401. Roles come from
config, never from the assertion. The jwt-bearer arm of /token is not
here yet, so no production path changes.

Workflows also get concurrency: a new push cancels the branch's older
builds, while publish and deploy serialize instead of cancelling.

Signed-off-by: Avelino <31996+avelino@users.noreply.github.com>
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved critical issues can cancel sibling release builds, fail CI on unused code, grant tenant roles without a tenant claim, and allow signing-key substitution through non-HTTPS JWKS retrieval.

6 open issues
What changed in this PR

Adds the ID-JAG validation foundation for enterprise-managed authorization in the Rust MCP server. The jwt-bearer token-endpoint integration remains deferred.

Changes:

  • Adds assertion validation, bounded JWKS caching, replay protection, and trusted-issuer/static-client configuration.
  • Adds authentication challenges, reload handling, tests, and operator documentation.
  • Adds concurrency controls to release and publishing workflows.
File Description
src/​server_auth/​oauth_as/​token.rs Updates test configuration fields.
src/​server_auth/​oauth_as/​test_helpers.rs Adds signing fixtures and fake issuer servers.
src/​server_auth/​oauth_as/​state.rs Adds static clients, replay tracking, and detailed cleanup reports.
src/​server_auth/​oauth_as/​register.rs Updates registration test configuration.
src/​server_auth/​oauth_as/​provider.rs Updates provider test configuration.
src/​server_auth/​oauth_as/​mod.rs Declares validation modules and exports shared types.
src/​server_auth/​oauth_as/​metadata.rs Updates metadata test configuration.
src/​server_auth/​oauth_as/​jwks.rs Adds bounded signing-key retrieval and caching.
src/​server_auth/​oauth_as/​e2e_tests.rs Updates end-to-end test configuration.
src/​server_auth/​oauth_as/​config.rs Adds trusted issuers, static clients, and validation rules.
src/​server_auth/​oauth_as/​authorize.rs Updates authorization test configuration.
src/​server_auth/​oauth_as/​assertion.rs Implements assertion checks and security tests.
src/​server_auth/​mod.rs Converts configured static clients without mutating state.
src/​serve/​stdio.rs Updates boot invariants for stdio.
src/​serve/​reload.rs Applies static clients and challenges; reports issuer restart requirements.
src/​serve/​reload_tests.rs Tests client preservation, restart reporting, and challenges.
src/​serve/​http.rs Adds authentication challenges and state lifecycle handling.
docs/​reference/​config-file.md Documents new authorization configuration fields.
docs/​howto/​oauth-as.md Adds managed-authorization and deployment guidance.
.github/​workflows/​release.yml Adds per-tag release concurrency.
.github/​workflows/​release-beta.yml Adds build cancellation and serialized publishing.
.github/​workflows/​publish-homebrew.yml Serializes Homebrew publishing.
.github/​workflows/​publish-crate.yml Adds per-ref crate publishing concurrency.

Review effort: Balanced

Comment thread .github/workflows/release-beta.yml Resolved
Comment thread src/server_auth/oauth_as/config.rs Resolved
Comment thread src/server_auth/oauth_as/jwks.rs Resolved
Comment thread src/server_auth/oauth_as/mod.rs Resolved
Comment thread docs/howto/oauth-as.md Resolved
Comment t 10BC8 hread docs/howto/oauth-as.md Resolved
Signed-off-by: Avelino <31996+avelino@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 4, 2026 13:21
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/server_auth/oauth_as/jwks.rs Resolved
Comment thread src/server_auth/oauth_as/token.rs Resolved
Comment thread src/server_auth/oauth_as/jwks.rs Resolved
Comment thread src/server_auth/oauth_as/token.rs Resolved
Signed-off-by: Avelino <31996+avelino@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 4, 2026 14:30
@avelino
avelino merged commit 5d9488d into main Nov 4, 2026
10 checks passed
@avelino
avelino deleted the feat/enterprise-managed-auth branch November 4, 2026 14:38
Copilot AI left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.await
.map_err(|why| err(StatusCode::BAD_REQUEST, "invalid_grant", why))?;

8 let a 10BC8 ccess_token = mint_access_token(ctx, &client_id, &validated.subject, &validated.roles)?;
Comment on lines +277 to +281
if claims
.nbf
.is_some_and(|nbf| nbf > now.saturating_add(MAX_CLOCK_SKEW_SECONDS))
{
return Err("assertion is not valid yet".to_string());
// Taken after the hit check, not before, so a cached key is never
// made to queue behind someone else's refresh.
let gate = self.gate(issuer);
let mut last_failure = gate.lock().await;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0