Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions cmd/thv-operator/api/v1beta1/mcpexternalauthconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1854,6 +1854,20 @@ type DCRUpstreamConfig struct {
// +kubebuilder:validation:MaxLength=2048
RegistrationEndpoint string `json:"registrationEndpoint,omitempty"`

// RotationKey is an optional operator-chosen label that is part of the
// cached registration's identity but is never sent to the upstream.
// Change it to make the proxies register a fresh client at their next
// start instead of reusing the cached one: for example after the
// upstream has dropped the registration (it rejects the stale client_id
// in the user's browser, so ToolHive cannot detect it) or when a
// rotation is required. The previous registration's row stays in storage,
// and upstream refresh tokens bound to the previous client_id stop
// refreshing, so affected users sign in again.
// +optional
// +kubebuilder:validation:Pattern=`^[A-Za-z0-9._-]+$`
// +kubebuilder:validation:MaxLength=64
RotationKey string `json:"rotationKey,omitempty"`

// InitialAccessTokenRef is an optional reference to a Kubernetes Secret
// carrying an RFC 7591 §3 initial access token. When set, the resolver
// presents the token value as a Bearer credential on the registration
Expand Down
1 change: 1 addition & 0 deletions cmd/thv-operator/pkg/controllerutil/authserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,7 @@ func buildDCRUpstreamRunConfig(
rc := &authserver.DCRUpstreamConfig{
DiscoveryURL: dcr.DiscoveryURL,
RegistrationEndpoint: dcr.RegistrationEndpoint,
RotationKey: dcr.RotationKey,
SoftwareID: dcr.SoftwareID,
SoftwareStatement: dcr.SoftwareStatement,
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/thv-operator/pkg/controllerutil/authserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,7 @@ func TestBuildAuthServerRunConfig(t *testing.T) {
UserInfo: &mcpv1beta1.UserInfoConfig{EndpointURL: "https://idp.example.com/userinfo"},
DCRConfig: &mcpv1beta1.DCRUpstreamConfig{
RegistrationEndpoint: "https://idp.example.com/register",
RotationKey: "2026-10",
},
},
},
Expand All @@ -1761,6 +1762,7 @@ func TestBuildAuthServerRunConfig(t *testing.T) {
assert.Equal(t, "https://idp.example.com/register",
upstream.OAuth2Config.DCRConfig.RegistrationEndpoint)
assert.Empty(t, upstream.OAuth2Config.DCRConfig.DiscoveryURL)
assert.Equal(t, "2026-10", upstream.OAuth2Config.DCRConfig.RotationKey)
// No InitialAccessTokenRef set: env var name should stay empty.
assert.Empty(t, upstream.OAuth2Config.DCRConfig.InitialAccessTokenEnvVar)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1736,6 +1736,20 @@ spec:
maxLength: 2048
pattern: ^https://[^\s?#]+[^/\s?#]$
type: string
rotationKey:
description: |-
RotationKey is an optional operator-chosen label that is part of the
cached registration's identity but is never sent to the upstream.
Change it to make the proxies register a fresh client at their next
start instead of reusing the cached one: for example after the
upstream has dropped the registration (it rejects the stale client_id
in the user's browser, so ToolHive cannot detect it) or when a
rotation is required. The previous registration's row stays in storage,
and upstream refresh tokens bound to the previous client_id stop
refreshing, so affected users sign in again.
maxLength: 64
pattern: ^[A-Za-z0-9._-]+$
type: string
softwareId:
description: |-
SoftwareID is the RFC 7591 "software_id" registration metadata value,
Expand Down Expand Up @@ -2116,6 +2130,20 @@ spec:
maxLength: 2048
pattern: ^https://[^\s?#]+[^/\s?#]$
type: string
rotationKey:
description: |-
RotationKey is an optional operator-chosen label that is part of the
cached registration's identity but is never sent to the upstream.
Change it to make the proxies register a fresh client at their next
start instead of reusing the cached one: for example after the
upstream has dropped the registration (it rejects the stale client_id
in the user's browser, so ToolHive cannot detect it) or when a
rotation is required. The previous registration's row stays in storage,
and upstream refresh tokens bound to the previous client_id stop
refreshing, so affected users sign in again.
maxLength: 64
pattern: ^[A-Za-z0-9._-]+$
type: string
softwareId:
description: |-
SoftwareID is the RFC 7591 "software_id" registration metadata value,
Expand Down Expand Up @@ -4622,6 +4650,20 @@ spec:
maxLength: 2048
pattern: ^https://[^\s?#]+[^/\s?#]$
type: string
rotationKey:
description: |-
RotationKey is an optional operator-chosen label that is part of the
cached registration's identity but is never sent to the upstream.
Change it to make the proxies register a fresh client at their next
start instead of reusing the cached one: for example after the
upstream has dropped the registration (it rejects the stale client_id
in the user's browser, so ToolHive cannot detect it) or when a
rotation is required. The previous registration's row stays in storage,
and upstream refresh tokens bound to the previous client_id stop
refreshing, so affected users sign in again.
maxLength: 64
pattern: ^[A-Za-z0-9._-]+$
type: string
softwareId:
description: |-
SoftwareID is the RFC 7591 "software_id" registration metadata value,
Expand Down Expand Up @@ -5002,6 +5044,20 @@ spec:
maxLength: 2048
pattern: ^https://[^\s?#]+[^/\s?#]$
type: string
rotationKey:
description: |-
RotationKey is an optional operator-chosen label that is part of the
cached registration's identity but is never sent to the upstream.
Change it to make the proxies register a fresh client at their next
start instead of reusing the cached one: for example after the
upstream has dropped the registration (it rejects the stale client_id
in the user's browser, so ToolHive cannot detect it) or when a
rotation is required. The previous registration's row stays in storage,
and upstream refresh tokens bound to the previous client_id stop
refreshing, so affected users sign in again.
maxLength: 64
pattern: ^[A-Za-z0-9._-]+$
type: string
softwareId:
description: |-
SoftwareID is the RFC 7591 "software_id" registration metadata value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,20 @@ spec:
maxLength: 2048
pattern: ^https://[^\s?#]+[^/\s?#]$
type: string
rotationKey:
description: |-
RotationKey is an optional operator-chosen label that is part of the
cached registration's identity but is never sent to the upstream.
Change it to make the proxies register a fresh client at their next
start instead of reusing the cached one: for example after the
upstream has dropped the registration (it rejects the stale client_id
in the user's browser, so ToolHive cannot detect it) or when a
rotation is required. The previous registration's row stays in storage,
and upstream refresh tokens bound to the previous client_id stop
refreshing, so affected users sign in again.
maxLength: 64
pattern: ^[A-Za-z0-9._-]+$
type: string
softwareId:
description: |-
SoftwareID is the RFC 7591 "software_id" registration metadata value,
Expand Down Expand Up @@ -1992,6 +2006,20 @@ spec:
maxLength: 2048
pattern: ^https://[^\s?#]+[^/\s?#]$
type: string
rotationKey:
description: |-
RotationKey is an optional operator-chosen label that is part of the
cached registration's identity but is never sent to the upstream.
Change it to make the proxies register a fresh client at their next
start instead of reusing the cached one: for example after the
upstream has dropped the registration (it rejects the stale client_id
in the user's browser, so ToolHive cannot detect it) or when a
rotation is required. The previous registration's row stays in storage,
and upstream refresh tokens bound to the previous client_id stop
refreshing, so affected users sign in again.
maxLength: 64
pattern: ^[A-Za-z0-9._-]+$
type: string
softwareId:
description: |-
SoftwareID is the RFC 7591 "software_id" registration metadata value,
Expand Down Expand Up @@ -6767,6 +6795,20 @@ spec:
maxLength: 2048
pattern: ^https://[^\s?#]+[^/\s?#]$
type: string
rotationKey:
description: |-
RotationKey is an optional operator-chosen label that is part of the
cached registration's identity but is never sent to the upstream.
Change it to make the proxies register a fresh client at their next
start instead of reusing the cached one: for example after the
upstream has dropped the registration (it rejects the stale client_id
in the user's browser, so ToolHive cannot detect it) or when a
rotation is required. The previous registration's row stays in storage,
and upstream refresh tokens bound to the previous client_id stop
refreshing, so affected users sign in again.
maxLength: 64
pattern: ^[A-Za-z0-9._-]+$
type: string
softwareId:
description: |-
SoftwareID is the RFC 7591 "software_id" registration metadata value,
Expand Down Expand Up @@ -7147,6 +7189,20 @@ spec:
maxLength: 2048
pattern: ^https://[^\s?#]+[^/\s?#]$
type: string
rotationKey:
description: |-
RotationKey is an optional operator-chosen label that is part of the
cached registration's identity but is never sent to the upstream.
Change it to make the proxies register a fresh client at their next
start instead of reusing the cached one: for example after the
upstream has dropped the registration (it rejects the stale client_id
in the user's browser, so ToolHive cannot detect it) or when a
rotation is required. The previous registration's row stays in storage,
and upstream refresh tokens bound to the previous client_id stop
refreshing, so affected users sign in again.
maxLength: 64
pattern: ^[A-Za-z0-9._-]+$
type: string
softwareId:
description: |-
SoftwareID is the RFC 7591 "software_id" registration metadata value,
Expand Down
Loading
Loading