@@ -18,6 +18,7 @@ import (
1818 "github.com/stacklok/toolhive/cmd/thv-operator/pkg/controllerutil"
1919 "github.com/stacklok/toolhive/cmd/thv-operator/pkg/oidc"
2020 "github.com/stacklok/toolhive/cmd/thv-operator/pkg/spectoconfig"
21+ "github.com/stacklok/toolhive/pkg/vmcp/auth/converters"
2122 authtypes "github.com/stacklok/toolhive/pkg/vmcp/auth/types"
2223 vmcpconfig "github.com/stacklok/toolhive/pkg/vmcp/config"
2324)
@@ -300,53 +301,37 @@ func (c *Converter) convertBackendAuthConfig(
300301 return nil , fmt .Errorf ("backend %s: unknown auth type %q" , backendName , crdConfig .Type )
301302}
302303
303- // convertExternalAuthConfigToStrategy converts MCPExternalAuthConfig to BackendAuthStrategy
304+ // convertExternalAuthConfigToStrategy converts MCPExternalAuthConfig to BackendAuthStrategy.
305+ // This uses the converter registry to consolidate conversion logic and apply token type normalization consistently.
306+ // The registry pattern makes adding new auth types easier and ensures conversion happens in one place.
304307func (* Converter ) convertExternalAuthConfigToStrategy (
305308 _ context.Context ,
306309 externalAuthConfig * mcpv1alpha1.MCPExternalAuthConfig ,
307310) (* authtypes.BackendAuthStrategy , error ) {
308- strategy := & authtypes.BackendAuthStrategy {}
309-
310- switch externalAuthConfig .Spec .Type {
311- case mcpv1alpha1 .ExternalAuthTypeUnauthenticated :
312- strategy .Type = authtypes .StrategyTypeUnauthenticated
313-
314- case mcpv1alpha1 .ExternalAuthTypeHeaderInjection :
315- if externalAuthConfig .Spec .HeaderInjection == nil {
316- return nil , fmt .Errorf ("headerInjection config is required when type is headerInjection" )
317- }
318-
319- strategy .Type = authtypes .StrategyTypeHeaderInjection
320- strategy .HeaderInjection = & authtypes.HeaderInjectionConfig {
321- HeaderName : externalAuthConfig .Spec .HeaderInjection .HeaderName ,
322- // The secret value will be mounted as an environment variable by the deployment controller
323- // Use the same env var naming convention as the deployment controller
324- HeaderValueEnv : controllerutil .GenerateUniqueHeaderInjectionEnvVarName (externalAuthConfig .Name ),
325- }
326-
327- case mcpv1alpha1 .ExternalAuthTypeTokenExchange :
328- if externalAuthConfig .Spec .TokenExchange == nil {
329- return nil , fmt .Errorf ("tokenExchange config is required when type is tokenExchange" )
330- }
331-
332- strategy .Type = authtypes .StrategyTypeTokenExchange
333- strategy .TokenExchange = & authtypes.TokenExchangeConfig {
334- TokenURL : externalAuthConfig .Spec .TokenExchange .TokenURL ,
335- ClientID : externalAuthConfig .Spec .TokenExchange .ClientID ,
336- Audience : externalAuthConfig .Spec .TokenExchange .Audience ,
337- Scopes : externalAuthConfig .Spec .TokenExchange .Scopes ,
338- SubjectTokenType : externalAuthConfig .Spec .TokenExchange .SubjectTokenType ,
339- }
311+ // Use the converter registry to convert to typed strategy
312+ registry := converters .DefaultRegistry ()
313+ converter , err := registry .GetConverter (externalAuthConfig .Spec .Type )
314+ if err != nil {
315+ return nil , err
316+ }
340317
341- // If client secret ref is set, use an environment variable
342- if externalAuthConfig .Spec .TokenExchange .ClientSecretRef != nil {
343- // The secret value will be mounted as an environment variable by the deployment controller
344- // Use the same env var naming convention as the deployment controller
345- strategy .TokenExchange .ClientSecretEnv = controllerutil .GenerateUniqueTokenExchangeEnvVarName (externalAuthConfig .Name )
346- }
318+ // Convert to typed BackendAuthStrategy (applies token type normalization)
319+ strategy , err := converter .ConvertToStrategy (externalAuthConfig )
320+ if err != nil {
321+ return nil , fmt .Errorf ("failed to convert external auth config to strategy: %w" , err )
322+ }
347323
348- default :
349- return nil , fmt .Errorf ("unknown external auth type: %s" , externalAuthConfig .Spec .Type )
324+ // Enrich with unique env var names per ExternalAuthConfig to avoid conflicts
325+ // when multiple configs of the same type reference different secrets
326+ if strategy .TokenExchange != nil &&
327+ externalAuthConfig .Spec .TokenExchange != nil &&
328+ externalAuthConfig .Spec .TokenExchange .ClientSecretRef != nil {
329+ strategy .TokenExchange .ClientSecretEnv = controllerutil .GenerateUniqueTokenExchangeEnvVarName (externalAuthConfig .Name )
330+ }
331+ if strategy .HeaderInjection != nil &&
332+ externalAuthConfig .Spec .HeaderInjection != nil &&
333+ externalAuthConfig .Spec .HeaderInjection .ValueSecretRef != nil {
334+ strategy .HeaderInjection .HeaderValueEnv = controllerutil .GenerateUniqueHeaderInjectionEnvVarName (externalAuthConfig .Name )
350335 }
351336
352337 return strategy , nil
0 commit comments