Skip to content

Wire identityFromToken through authserver config and runtime#5285

Open
jhrozek wants to merge 3 commits into
mainfrom
token_claim_mapping-4-translation
Open

Wire identityFromToken through authserver config and runtime#5285
jhrozek wants to merge 3 commits into
mainfrom
token_claim_mapping-4-translation

Conversation

@jhrozek
Copy link
Copy Markdown
Contributor

@jhrozek jhrozek commented May 14, 2026

Summary

The identityFromToken field was added to the v1beta1 CRD in #5269 but the translation layers that carry it from the CRD into the running auth server were missing, so the field was silently ignored.

  • Add the operator-side translation: v1beta1.IdentityFromTokenConfigauthserver.IdentityFromTokenRunConfig in buildOAuth2UpstreamRunConfig (mirrors TokenResponseMapping plumbing)
  • Add the runtime-side translation: authserver.IdentityFromTokenRunConfigupstream.IdentityFromTokenConfig in buildPureOAuth2Config
  • Add IdentityFromTokenRunConfig type to pkg/authserver/config.go alongside TokenResponseMappingRunConfig
  • Fix RegisterModifiers() — the call existed only in test TestMain functions, so @upstreamjwt modifier paths silently no-op'd in production; move the call into NewEmbeddedAuthServer and guard it with sync.Once to prevent races between concurrent constructors
  • Add startup validation: reject identity_from_token configs where subject_path is empty (would produce sub: "" in issued tokens)
  • Remove omitempty from SubjectPath struct tag to reflect its required-when-set semantics

Type of change

  • New feature

Test plan

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

Unit tests cover:

  • Round-trip translation on both the operator side (TestBuildAuthServerRunConfig) and runner side (TestBuildPureOAuth2ConfigIdentityFromToken) for nil, partial, and full-fields cases
  • New OAuth2UpstreamRunConfig.Validate cases for empty SubjectPath rejection

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.

Changes

File Change
cmd/thv-operator/pkg/controllerutil/authserver.go CRD → RunConfig translation for IdentityFromToken, moved inside buildOAuth2UpstreamRunConfig
cmd/thv-operator/pkg/controllerutil/authserver_test.go Three new table cases covering full, partial, and nil IdentityFromToken
pkg/authserver/config.go New IdentityFromTokenRunConfig type; field on OAuth2UpstreamRunConfig; Validate rejects empty SubjectPath
pkg/authserver/config_test.go Three new Validate cases for IdentityFromToken
pkg/authserver/runner/embeddedauthserver.go RegisterModifiers() call in constructor; RunConfig → upstream translation
pkg/authserver/runner/embeddedauthserver_test.go Three new subtests for nil/partial/full round-trip
pkg/authserver/upstream/identity_from_token.go sync.Once guard on modifier registration; fix stale v1alpha1v1beta1 comment

Special notes for reviewers

RegisterModifiers() previously relied on callers (only test TestMain functions) to register the @upstreamjwt gjson modifier before use. The sync.Once guard ensures registration happens exactly once even under concurrent NewEmbeddedAuthServer calls, which is safe because gjson's modifier map has no internal synchronisation.

Generated with Claude Code

jhrozek added 2 commits May 14, 2026 22:00
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.41%. Comparing base (17451d1) to head (1c1749c).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5285      +/-   ##
==========================================
+ Coverage   68.37%   68.41%   +0.04%     
==========================================
  Files         619      619              
  Lines       63318    63334      +16     
==========================================
+ Hits        43293    43333      +40     
+ Misses      16794    16765      -29     
- Partials     3231     3236       +5     

☔ 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.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jhrozek jhrozek requested a review from amirejaz as a code owner May 14, 2026 21:26
@github-actions github-actions Bot added size/M Medium PR: 300-599 lines changed and removed size/S Small PR: 100-299 lines changed labels May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Medium PR: 300-599 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant