Skip to content

Translate identityFromToken from CRD to runtime config#5280

Closed
jhrozek wants to merge 2 commits into
mainfrom
token_claim_mapping-4-translation
Closed

Translate identityFromToken from CRD to runtime config#5280
jhrozek wants to merge 2 commits into
mainfrom
token_claim_mapping-4-translation

Conversation

@jhrozek
Copy link
Copy Markdown
Contributor

@jhrozek jhrozek commented May 14, 2026

Summary

  • Phase 4 of the Snowflake / identityFromToken story (Cannot run a Snowflake MCP server behind ToolHive's MCPRemoteProxy #5150). The CRD field (Add identityFromToken to MCPExternalAuthConfig CRD #5269) and the OAuth2 provider integration (Wire identityFromToken into the OAuth2 upstream provider #5222) are both in main; this PR wires them together by threading the field through the two operator-side translation points that sit between them.
  • cmd/thv-operator/pkg/controllerutil/ translates the v1beta1 OAuth2UpstreamConfig.IdentityFromToken block into the authserver run-config. Mirrors the existing tokenResponseMapping plumbing exactly.
  • pkg/authserver/runner/'s embedded-auth-server bootstrapper translates the run-config field into the pkg/authserver/upstream.OAuth2Config the provider consumes. Same mechanical mirror.
  • upstream.RegisterModifiers() is called once in NewEmbeddedAuthServer so @upstreamjwt gjson paths actually resolve in production deployments. Without this, modifier-bearing paths silently returned empty strings at runtime.

Closes #5157

Type of change

  • New feature

Test plan

  • Unit tests (task test)
  • Linting (task lint-fix)

New tests cover the all-fields and nil cases for both translation points. The embeddedauthserver_test.go additions verify the runner-layer translation; authserver_test.go covers the operator-side builder.

API Compatibility

  • This PR does not break the v1beta1 API, OR the api-break-allowed label is applied and the migration guidance is described above.

Additive only — threads an existing CRD field through two translation layers.

Does this introduce a user-facing change?

Yes. Operators who configure identityFromToken on an OAuth2 upstream in a VirtualMCPServer can now deploy to a real cluster and have the embedded auth server honour the field. Previously, the CRD accepted the config but it was silently discarded before reaching the provider.

Implementation plan

Approved implementation plan

Phase 4 of the Snowflake / identityFromToken story (#5150):

Generated with Claude Code

jhrozek added 2 commits May 14, 2026 13:33
Add the operator-side and runtime-side translation that carries
IdentityFromToken from MCPExternalAuthConfig (v1beta1 CRD) through
the authserver run-config and into upstream.OAuth2Config so the
provider added in the previous commit actually receives the field.

Two translation points mirror the existing TokenResponseMapping
plumbing:

  * cmd/thv-operator/pkg/controllerutil/authserver.go
    CRD v1beta1.IdentityFromTokenConfig
       -> authserver.IdentityFromTokenRunConfig (operator path)
  * pkg/authserver/runner/embeddedauthserver.go
    authserver.IdentityFromTokenRunConfig
       -> upstream.IdentityFromTokenConfig (runtime path)

A new IdentityFromTokenRunConfig type lives next to
TokenResponseMappingRunConfig in pkg/authserver/config.go.

Tests cover the round-trip on both sides and the nil-config case
(no spurious allocation).
IdentityFromToken paths that use the `@upstreamjwt` modifier (e.g.
`access_token|@upstreamjwt|sub` for upstreams that embed identity
inside a JWS access token) require RegisterModifiers() to run before
any extraction. Until now the call lived only in test TestMain
functions, so production paths silently no-op'd and operators saw a
generic "path not found" error.

Add the call near the top of NewEmbeddedAuthServer. Protect the
gjson.AddModifier write with a sync.Once so concurrent constructors
(parallel test cases, thundering-herd restarts) do not race on the
gjson global modifier map.
@github-actions github-actions Bot added the size/S Small PR: 100-299 lines changed label May 14, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.34%. Comparing base (8c84c05) to head (3d7f96b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5280      +/-   ##
==========================================
+ Coverage   68.33%   68.34%   +0.01%     
==========================================
  Files         619      619              
  Lines       63325    63339      +14     
==========================================
+ Hits        43274    43290      +16     
+ Misses      16816    16815       -1     
+ Partials     3235     3234       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jhrozek
Copy link
Copy Markdown
Contributor Author

jhrozek commented May 14, 2026

sorry claude got PR horny

@jhrozek jhrozek closed this May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/S Small PR: 100-299 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Translate identityFromToken from CRD to runtime config

1 participant