Skip to content

feat(serveredition): generic OIDC provider, front door behind an ingress, telemetry v13 (Spec 107 PR-B) - #1292

Merged
Dumbris merged 37 commits into
mainfrom
107-b-oidc-front-door
Sep 18, 2026
Merged

Dumbris merged 37 commits into
mainfrom
107-b-oidc-front-door

Conversation

@Dumbris

@Dumbris Dumbris commented Sep 16, 2026

Copy link
Copy Markdown
Member

Summary

Stacked on #1287 — merge that first; the base retargets to main automatically.

Spec 107 PR-B (Phase B.1–B.6, T032–T066): generic OIDC provider for the server edition's front door, running behind an ingress/reverse proxy, plus telemetry v13.

  • Generic OIDC provider (internal/serveredition/auth/{oidc_provider.go,oidc_jwks.go}, 142 lines against the 150-line budget): stdlib JWK→key parsing (crypto/rsa, crypto/ecdsa), per-kid cache, discovery, PKCE + nonce login, RS256 id_token verification (iss/aud/azp/exp/iat/nonce), /userinfo fallback, and the full ErrorMode fail-closed matrix (bad signature, wrong issuer/audience, missing nonce, alg:none/HS256 confusion, malformed groups claim, discovery/token-endpoint failures) — every case refuses the login with no session issued, distinguishing the "closed" 403 class from the "unavailable" 503 class (FR-024).
  • Front door behind an ingress (FR-027): edition-neutral trusted_proxies config gates whether X-Forwarded-Proto/X-Real-IP/X-Forwarded-Host are believed; session_cookie_secure: auto derives the cookie's Secure attribute from public_url, in-process TLS, or a trusted proxy's forwarded scheme — an untrusted peer cannot spoof https to change the decision.
  • Config wiring: IssuerURL, AllowInsecureIssuer, Scopes, GroupsClaim, EmailVerifiedPolicy, DisplayName on ServerEditionOAuthConfig; PublicURL/SessionCookieSecure on ServerEditionConfig; build-tagged accessors; public GET /api/v1/auth/provider probe so the Web UI learns the edition before authenticating; config-load path fixed (round 6) so a resolved OAuth client secret is never round-tripped back into mcp_config.json by an unrelated PATCH /api/v1/config.
  • Telemetry v13: server_edition_enabled, idp_provider, member_count_bucket (deliberately not user_count_bucket — see the rejected finding in cross-review round 6: a user-prefixed key would trip the PII scanner's home-dir-basename check on every USER user-topology server container) added to the heartbeat payload; personal builds report server_edition_enabled=false, idp_provider="none".
  • scripts/dev-server-edition.sh: local verification rig implementing quickstart §0–§4 and §6 (--phase b|c|d), used for both the fixed test suite and the real-instance verification below.

Key config

Key Type Notes
trusted_proxies []string (top-level, edition-neutral) CIDRs/IPs trusted to set X-Forwarded-*
server_edition.public_url string restart-pinned; https scheme forces Secure cookies unconditionally
server_edition.session_cookie_secure "auto" | "true" | "false" default auto
server_edition.oauth.provider "oidc" (new; alongside existing) generic OIDC provider
server_edition.oauth.issuer_url string, must be absolute https unless allow_insecure_issuer (loopback dev only)
server_edition.oauth.groups_claim, .email_verified_policy, .display_name FR-008/FR-030

Verification gates (short)

All green on HEAD 873145b64 (re-run in full after cross-review round 6 touched the config load path, oauth_handler.go, and telemetry.go): both editions build; go vet both tags; golangci-lint v2.9.0 both tag sets (0 issues); server-edition + personal race suites (incl. the internal/server/internal/httpapi CI-skip sweep); frozen tool-surface goldens; go test ./cmd/..., ./tests/oauthserver/... incl. OAUTH_INTEGRATION_TESTS=1; make swagger-verify + TestContractsInSync; gen-roadmap.py --check; frontend vitest (1284 tests) + npm run build; gofmt -l clean; check-settings-parity.py (61 settings consistent); Swift swift test (1166/1167 — the one failure is the same pre-existing environmental red herring as PR-A, AppLifecycleTests colliding with a live local tray journal); isolated scripts/test-api-e2e.sh (65/65). Full command-by-command log: specs/107-server-edition-sso-hardening/verification.md## PR-B### Automated checks.

Real-instance verification (### Real instance in the same file): headless OIDC login end-to-end against a fake IdP (tests/oauthserver), groups on /auth/me, agent-token mint + /mcp initialize/tools/list → 200, the full ErrorMode tamper matrix, and the cookie-Secure matrix behind a simulated trusted-vs-untrusted reverse proxy. Two noted discrepancies between the task text and the shipped code (task rule: code wins) are called out inline: quickstart §6 is reachable only via --phase d, which needs PR-C's entitlement filtering (§5) first — verified directly with curl instead; and the telemetry wire key is member_count_bucket, not user_count_bucket.

6 rounds of cross-model review (opencode run --model github-copilot/gpt-6-astra, fallback gpt-5.6-sol), all findings verified against the live tree before fixing; details in verification.md### Cross-review.

Related #1169 (live-role reuse).

🤖 Generated with Claude Code

Dumbris and others added 29 commits September 16, 2026 10:45
…al IdPs

Generic OIDC provider, IdP-group → server allowlist, attributable JSONL
audit line, and a freeze/cut of the latent multiuser/credential-injection
code, split into four PRs (A freeze/cut, B OIDC + front door + telemetry,
C entitlement predicate + tenant session, D audit line).

Judge-panel drafted; cross-model reviewed over nine rounds (codex gpt-5.6-sol),
~130 findings resolved. Un-parks roadmap epic sso.
… and normalise removed config keys (Spec 107 PR-A)

Related #1177
Resolves the add/add conflict in .github/RELEASE_NOTICE.md by keeping the
branch copy, whose first section is byte-identical to main's Spec 105 notice
(#1279) and which appends the Spec 107 PR-A entries after it.
…ns, groups capture and subject binding (Spec 107 PR-B)

Related #1169
…e security and forced MCP auth (Spec 107 PR-B)
…ed proxies, cookie security policy, forced MCP auth, provider probe (Spec 107 PR-B)
… keys; telemetry v13 server-edition fields (Spec 107 PR-B)
T062/T063: real-instance verification of the OIDC front door (happy-path
login, groups, /auth/me, agent-token mint + /mcp initialize/tools-list,
ErrorMode tamper matrix, cookie Secure matrix behind a simulated trusted vs
untrusted proxy) and the telemetry v13 payload (server vs personal). T064:
full gate set re-run on HEAD after cross-review round 6 touched the config
load path, oauth_handler.go and telemetry.go — all green. T066: tick
completed PR-B tasks (T032-T066); ROADMAP.md regenerated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 16, 2026

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4bd0dfa
Status: ✅  Deploy successful!
Preview URL: https://35e61f9c.mcpproxy-docs.pages.dev
Branch Preview URL: https://107-b-oidc-front-door.mcpproxy-docs.pages.dev

View logs

@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

📦 Build Artifacts

Workflow Run: View Run
Branch: 107-b-oidc-front-door

Available Artifacts

  • archive-darwin-amd64 (30 MB)
  • archive-darwin-arm64 (27 MB)
  • archive-linux-amd64 (18 MB)
  • archive-linux-arm64 (16 MB)
  • archive-windows-amd64 (30 MB)
  • archive-windows-arm64 (26 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (24 MB)
  • installer-dmg-darwin-arm64 (21 MB)
  • smart-mcp-proxymcpproxy-goWRNKHL.dockerbuild (0 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 35338900347 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@codecov-commenter

codecov-commenter commented Sep 16, 2026

Copy link
Copy Markdown

Dumbris and others added 5 commits September 17, 2026 02:16
…1288)

This branch diverged from main before #1288 landed, so PR-B's CI hit the
exact regression it fixed: handleAddFromRegistry's success path dereferenced
a nil cfg, chi's recoverer turned the panic into a bare 500, and the
recovered hardware fault corrupted the Go heap on windows/amd64 under Go
1.26 (golang/go#81238) — the internal/httpapi test binary crashed with
"found pointer to free object" and took the whole Windows unit-test job (and
the binaries job's httpapi/scanner test bundle) down with it. Cherry-picked
the same fix main already carries: the nil-config guard with a JSON 500 (and
its pinning test), plus the unrelated Pass-2 temp-dir teardown race fix in
the scanner test this same upstream commit bundled.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Dumbris and others added 2 commits September 18, 2026 13:39
# Conflicts:
#	.github/RELEASE_NOTICE.md
#	ROADMAP.md
#	docs/development/server-edition-multiuser-auth.md
#	frontend/src/views/settings/fields.ts
#	frontend/tests/unit/settings-server-edition-wording.spec.ts
#	internal/config/config.go
#	internal/config/config_validate_serveredition.go
#	internal/config/server_edition_config.go
#	internal/serveredition/api/connector_provider.go
#	internal/serveredition/auth/oauth_handler.go
#	internal/serveredition/auth/oauth_handler_test.go
#	internal/serveredition/auth/oauth_providers.go
#	internal/serveredition/setup.go
#	roadmap.yaml
#	specs/107-server-edition-sso-hardening/tasks.md
#	specs/107-server-edition-sso-hardening/verification.md
…er probe

The merge of origin/main (#1294, shared in-flight auth probe) into
107-b-oidc-front-door (#1292, generic OIDC provider) combined without a
conflict, but PR-B's auth store change (probe() now calls
authApi.getProvider() instead of api.getStatus() for edition detection,
Spec 107 FR-030/FR-041) left the test file's mocks pointed at the old
api.getStatus() call, so every test silently no-oped through probe()'s
catch block. Repoint the spy at authApi.getProvider() and update the
resolved payload shape ({ display_name } instead of
{ data: { edition } }); the in-flight-probe-sharing behaviour under test
is unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
} else {
fmt.Println("Test Credentials (username / password / groups):")
for user, pass := range opts.ValidUsers {
fmt.Printf(" %s / %s / %v\n", user, pass, opts.UserClaims[user][opts.GroupsClaim])
…gnature

Mirrors main's ce5c2f7 fix for the same loadConfig signature mismatch
that broke the Build Binaries CI job on this PR.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Dumbris
Dumbris merged commit 1f2cc18 into main Sep 18, 2026
54 of 55 checks passed
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.

3 participants