@@ -33,7 +33,7 @@ You'll need:
3333
3434## Choose your authentication approach
3535
36- There are four main ways to authenticate with MCP servers running in Kubernetes:
36+ There are several ways to authenticate with MCP servers running in Kubernetes:
3737
3838### Approach 1: External identity provider authentication
3939
@@ -44,18 +44,30 @@ providers like Google, GitHub, Microsoft Entra ID, Okta, or Auth0.
4444
4545<OidcPrerequisites />
4646
47- ### Approach 2: Shared OIDC configuration with ConfigMap
47+ ### Approach 2: Shared OIDC configuration with MCPOIDCConfig
4848
4949Use this when you want to share the same OIDC configuration across multiple
50- MCPServers. This is ideal for managing multiple servers with the same external
51- identity provider .
50+ MCPServers or VirtualMCPServers. The ` MCPOIDCConfig ` CRD provides a dedicated,
51+ validated resource for managing shared OIDC settings at the platform level .
5252
5353** Prerequisites for shared OIDC:**
5454
5555- External identity provider configured (same as Approach 1)
56- - Understanding of Kubernetes ConfigMaps
5756
58- ### Approach 3: Kubernetes service-to-service authentication
57+ ### Approach 3: Shared OIDC configuration with ConfigMap (legacy)
58+
59+ :::warning[ Prefer MCPOIDCConfig]
60+
61+ For new deployments, use Approach 2 (` MCPOIDCConfig ` ) instead of a ConfigMap.
62+ ` MCPOIDCConfig ` provides built-in validation, status tracking, and lifecycle
63+ management.
64+
65+ :::
66+
67+ This approach predates MCPOIDCConfig and remains supported. Use this when you
68+ want to share OIDC configuration via a ConfigMap.
69+
70+ ### Approach 4: Kubernetes service-to-service authentication
5971
6072Use this when you have client applications running in the same Kubernetes
6173cluster that need to call MCP servers. This approach uses Kubernetes service
@@ -66,7 +78,7 @@ account tokens for authentication.
6678- Client applications running in Kubernetes pods
6779- Understanding of Kubernetes service accounts and RBAC
6880
69- ### Approach 4 : Embedded authorization server authentication
81+ ### Approach 5 : Embedded authorization server authentication
7082
7183Use this when you want ToolHive to handle the full OAuth flow, including
7284redirecting users to an upstream identity provider for authentication. This
@@ -82,8 +94,131 @@ For conceptual background, see
8294- A registered OAuth application/client with your upstream provider
8395- Client ID and client secret from your upstream provider
8496
97+ ## Set up shared OIDC configuration with MCPOIDCConfig
98+
99+ The ` MCPOIDCConfig ` CRD lets you define OIDC provider settings once and
100+ reference them from multiple MCPServer or VirtualMCPServer resources. Each
101+ server specifies its own ` audience ` (and optionally ` scopes ` ) to maintain token
102+ isolation.
103+
104+ ** Step 1: Create an MCPOIDCConfig resource**
105+
106+ <Tabs groupId = " oidc-type" >
107+ <TabItem value = " inline" label = " External IdP" default >
108+
109+ ``` yaml title="shared-oidc-config.yaml"
110+ apiVersion : toolhive.stacklok.dev/v1alpha1
111+ kind : MCPOIDCConfig
112+ metadata :
113+ name : production-oidc
114+ namespace : toolhive-system
115+ spec :
116+ type : inline
117+ inline :
118+ issuer : ' https://auth.example.com'
119+ clientId : ' your-client-id'
120+ clientSecretRef :
121+ name : oidc-secret
122+ key : client-secret
123+ jwksUrl : ' https://auth.example.com/.well-known/jwks.json'
124+ ` ` `
125+
126+ </TabItem>
127+ <TabItem value="k8s" label="Kubernetes service account">
128+
129+ ` ` ` yaml title="k8s-oidc-config.yaml"
130+ apiVersion : toolhive.stacklok.dev/v1alpha1
131+ kind : MCPOIDCConfig
132+ metadata :
133+ name : k8s-sa-oidc
134+ namespace : toolhive-system
135+ spec :
136+ type : kubernetesServiceAccount
137+ kubernetesServiceAccount :
138+ serviceAccount : mcp-client
139+ namespace : client-apps
140+ ` ` `
141+
142+ </TabItem>
143+ </Tabs>
144+
145+ Apply the resource:
146+
147+ ` ` ` bash
148+ kubectl apply -f <YOUR_OIDC_CONFIG_FILE>.yaml
149+ ```
150+
151+ ** Step 2: Reference MCPOIDCConfig from an MCPServer**
152+
153+ Use ` oidcConfigRef ` instead of inline ` oidcConfig ` . Each server must set a
154+ unique ` audience ` to prevent token replay across servers:
155+
156+ ``` yaml title="mcp-server-shared-oidc.yaml"
157+ apiVersion : toolhive.stacklok.dev/v1alpha1
158+ kind : MCPServer
159+ metadata :
160+ name : weather-server
161+ namespace : toolhive-system
162+ spec :
163+ image : ghcr.io/stackloklabs/weather-mcp/server
164+ transport : streamable-http
165+ proxyPort : 8080
166+ permissionProfile :
167+ type : builtin
168+ name : network
169+ # highlight-start
170+ oidcConfigRef :
171+ name : production-oidc
172+ audience : weather-server
173+ scopes :
174+ - openid
175+ # highlight-end
176+ ```
177+
178+ ``` bash
179+ kubectl apply -f mcp-server-shared-oidc.yaml
180+ ```
181+
182+ ** Step 3: Verify**
183+
184+ Check the MCPOIDCConfig status:
185+
186+ ``` bash
187+ kubectl get mcpoidc -n toolhive-system
188+ ```
189+
190+ The ` REFERENCES ` column shows which workloads use this config. The ` READY `
191+ column confirms validation passed.
192+
193+ ### Benefits of MCPOIDCConfig
194+
195+ - ** Centralized management** : update provider settings in one place for all
196+ servers
197+ - ** Built-in validation** : CEL rules catch misconfiguration at admission time
198+ - ** Status tracking** : see which workloads reference the config and whether it
199+ is valid
200+ - ** Lifecycle management** : deletion is blocked while workloads reference the
201+ config
202+
203+ :::info[ Inline oidcConfig deprecation]
204+
205+ The inline ` spec.oidcConfig ` field on MCPServer is deprecated and will be
206+ removed in ` v1beta1 ` . Use ` oidcConfigRef ` to reference a shared MCPOIDCConfig
207+ resource instead. You cannot set both fields on the same MCPServer.
208+
209+ :::
210+
85211## Set up external identity provider authentication
86212
213+ :::note[ Consider MCPOIDCConfig]
214+
215+ For new deployments, consider using ` oidcConfigRef ` with a shared MCPOIDCConfig
216+ resource instead of inline ` oidcConfig ` . See
217+ [ Set up shared OIDC configuration] ( #set-up-shared-oidc-configuration-with-mcpoidcconfig )
218+ above.
219+
220+ :::
221+
87222** Step 1: Create an MCPServer with external OIDC**
88223
89224Create an ` MCPServer ` resource configured to accept tokens from your external
@@ -99,7 +234,7 @@ metadata:
99234spec :
100235 image : ghcr.io/stackloklabs/weather-mcp/server
101236 transport : sse
102- port : 8080
237+ proxyPort : 8080
103238 permissionProfile :
104239 type : builtin
105240 name : network
@@ -185,7 +320,7 @@ metadata:
185320spec :
186321 image : ghcr.io/stackloklabs/weather-mcp/server
187322 transport : sse
188- port : 8080
323+ proxyPort : 8080
189324 permissionProfile :
190325 type : builtin
191326 name : network
@@ -249,7 +384,7 @@ metadata:
249384spec :
250385 image : ghcr.io/stackloklabs/weather-mcp/server
251386 transport : sse
252- port : 8080
387+ proxyPort : 8080
253388 permissionProfile :
254389 type : builtin
255390 name : network
@@ -629,7 +764,11 @@ standard `name` field.
629764# # Set up authorization
630765
631766All authentication approaches can use the same authorization configuration using
632- Cedar policies.
767+ Cedar policies. When using the embedded authorization server (Approach 5), Cedar
768+ policies can also evaluate upstream identity provider claims such as group
769+ membership. See
770+ [Upstream identity provider claims](../concepts/cedar-policies.mdx#upstream-identity-provider-claims)
771+ for details.
633772
634773**Step 1: Create authorization configuration**
635774
@@ -678,7 +817,7 @@ metadata:
678817spec:
679818 image: ghcr.io/stackloklabs/weather-mcp/server
680819 transport: sse
681- port : 8080
820+ proxyPort : 8080
682821 permissionProfile:
683822 type: builtin
684823 name: network
0 commit comments