Fix round-36 issues: DCR validation, auth-method default, shared metadata task, replay false-positive

Four verified fixes from the round-36 agent team (each confirmed against source
before acting):

- settings.go: Config.Validate now skips the client-credential block when
  Dynamic Client Registration is enabled and no clientID is pre-provisioned
  (RFC 7591 provides credentials at registration). Previously the
  unconditional 'clientID is required' made DCR unreachable via New.
- dynamic_client_registration.go: default registered token_endpoint_auth_method
  to client_secret_post to match the plugin's runtime default; an enforcing
  IdP would otherwise reject the plugin's token exchange.
- utilities.go: gate the shared per-provider singleton-metadata-refresh task
  stop on lastInstance (matching singleton-token-cleanup) so one instance's
  tear down no longer kills 2h metadata refresh for a surviving sibling.
- token_manager.go: stop self-recording the JTI into the per-instance
  tokenBlacklist on every verify. On the cookie path the same valid token is
  re-presented per request; an LRU eviction of the raw-token cache (MaxSize
  1000 / 5 MiB) then turned a legitimate cache miss into a false 'token
  replay detected'. Replay tracking stays in the shared shardedReplayCache.

Regression tests: new review_r36_regression_test.go (4 tests); updated
dynamic_client_registration_test.go and security_edge_cases_test.go which had
encoded the old defaults.

Verified: full source-order suite, full -race -count=1 -shuffle=on ./...
(all packages), and golangci-lint run ./... (0 issues).
This commit is contained in:
2026-08-13 00:14:21 +01:00
parent 35d26078f0
commit 0358d9b970
7 changed files with 254 additions and 64 deletions
+7 -2
View File
@@ -244,8 +244,13 @@ func (t *TraefikOidc) Close() error {
if lastInstance {
_ = rm.StopBackgroundTask("singleton-token-cleanup") // best effort, last instance only
}
// Stop metadata refresh task using same hash-based name as startMetadataRefresh
if t.providerURL != "" {
// Stop metadata refresh task using same hash-based name as
// startMetadataRefresh. The name derives only from providerURL
// (main.go), so it is SHARED by every live instance pointing at the
// same provider; stopping it on one instance's Close would kill 2h
// metadata refresh for its surviving sibling (which never re-registers).
// Gate on lastInstance, matching singleton-token-cleanup above.
if lastInstance && t.providerURL != "" {
hash := sha256.Sum256([]byte(t.providerURL))
taskName := "singleton-metadata-refresh-" + hex.EncodeToString(hash[:])[0:6]
_ = rm.StopBackgroundTask(taskName) // Safe to ignore: best effort cleanup