@@ -98,6 +98,337 @@ curl -H "Authorization: Bearer <your-jwt-token>" \
9898 < toolhive-server-url>
9999```
100100
101+ ## Set up proxy authentication
102+
103+ ToolHive provides a standalone ` thv proxy ` command that creates transparent HTTP
104+ proxies with advanced authentication capabilities. This is different from using
105+ ` thv run ` with authentication—the proxy command creates a standalone proxy
106+ process without managing workloads or containers.
107+
108+ ### When to use proxy authentication
109+
110+ Use the ` thv proxy ` command when you need:
111+
112+ - ** Outgoing authentication** : Authenticate to remote MCP servers using
113+ OAuth/OIDC, with the proxy handling token management and refresh
114+ - ** Incoming authentication** : Protect a proxy endpoint with OIDC validation,
115+ requiring clients to provide valid JWT tokens
116+ - ** Bidirectional authentication** : Secure both incoming requests to the proxy
117+ and outgoing requests to remote servers
118+ - ** Dynamic client registration** : Automatically register OAuth clients using
119+ RFC 7591, eliminating the need for pre-configuration
120+ - ** Standalone proxy** : Run a proxy without creating a managed workload
121+
122+ ### Basic proxy with outgoing authentication
123+
124+ To create a proxy that authenticates to a remote MCP server:
125+
126+ ``` bash
127+ thv proxy my-server \
128+ --target-uri https://api.example.com \
129+ --remote-auth \
130+ --remote-auth-issuer https://auth.example.com \
131+ --remote-auth-client-id my-client-id \
132+ --remote-auth-client-secret-file /path/to/secret
133+ ```
134+
135+ The proxy will:
136+
137+ 1 . Handle the OAuth/OIDC flow with the remote server
138+ 2 . Manage token storage and automatic refresh
139+ 3 . Forward authenticated requests transparently
140+
141+ Your clients connect to the local proxy without needing to handle
142+ authentication.
143+
144+ ### Proxy with incoming authentication
145+
146+ To protect the proxy endpoint itself with OIDC validation:
147+
148+ ``` bash
149+ thv proxy my-server \
150+ --target-uri http://localhost:8080 \
151+ --oidc-issuer https://auth.example.com \
152+ --oidc-audience my-audience \
153+ --oidc-client-id my-client-id
154+ ```
155+
156+ Clients must include a valid JWT token when connecting to the proxy.
157+
158+ ### Bidirectional proxy authentication
159+
160+ Combine both incoming and outgoing authentication for end-to-end security:
161+
162+ ``` bash
163+ thv proxy my-server \
164+ --target-uri https://api.example.com \
165+ --remote-auth \
166+ --remote-auth-issuer https://remote-auth.example.com \
167+ --remote-auth-client-id remote-client-id \
168+ --remote-auth-client-secret-file /path/to/remote-secret \
169+ --oidc-issuer https://local-auth.example.com \
170+ --oidc-audience my-audience \
171+ --oidc-client-id local-client-id
172+ ```
173+
174+ ### Authentication modes
175+
176+ The ` thv proxy ` command supports four authentication scenarios:
177+
178+ 1 . ** No authentication** : Simple transparent forwarding
179+ 2 . ** Outgoing authentication** : Authenticate to remote MCP servers using
180+ OAuth/OIDC
181+ 3 . ** Incoming authentication** : Protect the proxy endpoint with OIDC validation
182+ 4 . ** Bidirectional** : Both incoming and outgoing authentication
183+
184+ ### OAuth2 authentication (non-OIDC)
185+
186+ For non-OIDC OAuth2 servers, specify the authorization and token endpoints
187+ explicitly:
188+
189+ ``` bash
190+ thv proxy my-server \
191+ --target-uri https://api.example.com \
192+ --remote-auth \
193+ --remote-auth-authorize-url https://auth.example.com/oauth/authorize \
194+ --remote-auth-token-url https://auth.example.com/oauth/token \
195+ --remote-auth-client-id my-client-id \
196+ --remote-auth-client-secret-file /path/to/secret
197+ ```
198+
199+ ### Auto-detect authentication
200+
201+ The proxy can automatically detect if a remote server requires authentication by
202+ examining WWW-Authenticate headers:
203+
204+ ``` bash
205+ thv proxy my-server \
206+ --target-uri https://protected-api.com \
207+ --remote-auth-client-id my-client-id
208+ ```
209+
210+ When authentication is detected, the proxy automatically initiates the
211+ appropriate OAuth flow.
212+
213+ ### Dynamic client registration
214+
215+ When no client credentials are provided, the proxy can automatically register an
216+ OAuth client using RFC 7591 dynamic client registration:
217+
218+ ``` bash
219+ thv proxy my-server \
220+ --target-uri https://protected-api.com \
221+ --remote-auth \
222+ --remote-auth-issuer https://auth.example.com
223+ ```
224+
225+ This feature:
226+
227+ - Eliminates the need to pre-configure OAuth clients
228+ - Automatically discovers the registration endpoint via OIDC
229+ - Supports PKCE flow for enhanced security
230+
231+ :::info
232+
233+ Dynamic client registration requires the remote authorization server to support
234+ RFC 7591. Not all OAuth providers support this feature.
235+
236+ :::
237+
238+ ### Token introspection
239+
240+ For advanced scenarios, you can use token introspection for incoming
241+ authentication:
242+
243+ ``` bash
244+ thv proxy my-server \
245+ --target-uri http://localhost:8080 \
246+ --oidc-issuer https://auth.example.com \
247+ --oidc-audience my-audience \
248+ --oidc-client-id my-client-id \
249+ --oidc-client-secret my-client-secret \
250+ --oidc-introspection-url https://auth.example.com/oauth/introspect
251+ ```
252+
253+ ### Advanced proxy configuration
254+
255+ #### Custom OAuth scopes
256+
257+ Specify the OAuth scopes required by the remote server:
258+
259+ ``` bash
260+ thv proxy my-server \
261+ --target-uri https://api.example.com \
262+ --remote-auth \
263+ --remote-auth-issuer https://auth.example.com \
264+ --remote-auth-client-id my-client-id \
265+ --remote-auth-client-secret-file /path/to/secret \
266+ --remote-auth-scopes openid,profile,email,custom-scope
267+ ```
268+
269+ :::note
270+
271+ If ` --remote-auth-scopes ` is not specified, OIDC authentication defaults to
272+ ` openid,profile,email ` .
273+
274+ :::
275+
276+ #### Authentication timeout
277+
278+ Adjust the timeout for slow networks or interactive authentication flows:
279+
280+ ``` bash
281+ thv proxy my-server \
282+ --target-uri https://api.example.com \
283+ --remote-auth \
284+ --remote-auth-issuer https://auth.example.com \
285+ --remote-auth-client-id my-client-id \
286+ --remote-auth-client-secret-file /path/to/secret \
287+ --remote-auth-timeout 2m
288+ ```
289+
290+ #### Headless authentication
291+
292+ For non-interactive environments (CI/CD, servers), skip browser-based OAuth
293+ flows:
294+
295+ ``` bash
296+ thv proxy my-server \
297+ --target-uri https://api.example.com \
298+ --remote-auth \
299+ --remote-auth-issuer https://auth.example.com \
300+ --remote-auth-client-id my-client-id \
301+ --remote-auth-client-secret-file /path/to/secret \
302+ --remote-auth-skip-browser
303+ ```
304+
305+ This requires client credentials flow or pre-authorized tokens.
306+
307+ #### Custom proxy host and port
308+
309+ By default, the proxy listens on ` 127.0.0.1 ` with a random port. To specify
310+ custom values:
311+
312+ ``` bash
313+ thv proxy my-server \
314+ --target-uri http://localhost:8080 \
315+ --host 0.0.0.0 \
316+ --port 8000
317+ ```
318+
319+ #### Custom OAuth callback port
320+
321+ The proxy uses a temporary HTTP server for OAuth callbacks during
322+ authentication. To specify a custom callback port:
323+
324+ ``` bash
325+ thv proxy my-server \
326+ --target-uri https://api.example.com \
327+ --remote-auth \
328+ --remote-auth-issuer https://auth.example.com \
329+ --remote-auth-client-id my-client-id \
330+ --remote-auth-client-secret-file /path/to/secret \
331+ --remote-auth-callback-port 9000
332+ ```
333+
334+ The default callback port is ` 8666 ` .
335+
336+ ### Credential management
337+
338+ #### Client secret sources
339+
340+ OAuth client secrets can be provided via three methods (in order of precedence):
341+
342+ 1 . ` --remote-auth-client-secret ` flag (not recommended for production)
343+ 2 . ` --remote-auth-client-secret-file ` flag (recommended)
344+ 3 . ` TOOLHIVE_REMOTE_OAUTH_CLIENT_SECRET ` environment variable
345+
346+ :::warning[ Secure credential handling]
347+
348+ Always use ` --remote-auth-client-secret-file ` instead of
349+ ` --remote-auth-client-secret ` in production environments. The file-based
350+ approach prevents credentials from appearing in process lists or command
351+ history.
352+
353+ :::
354+
355+ #### Using environment variables
356+
357+ ``` bash
358+ export TOOLHIVE_REMOTE_OAUTH_CLIENT_SECRET=" your-secret-here"
359+ thv proxy my-server \
360+ --target-uri https://api.example.com \
361+ --remote-auth \
362+ --remote-auth-issuer https://auth.example.com \
363+ --remote-auth-client-id my-client-id
364+ ```
365+
366+ #### Using secret files
367+
368+ ``` bash
369+ echo " your-secret-here" > /secure/path/secret.txt
370+ chmod 600 /secure/path/secret.txt
371+
372+ thv proxy my-server \
373+ --target-uri https://api.example.com \
374+ --remote-auth \
375+ --remote-auth-issuer https://auth.example.com \
376+ --remote-auth-client-id my-client-id \
377+ --remote-auth-client-secret-file /secure/path/secret.txt
378+ ```
379+
380+ ### Common proxy use cases
381+
382+ #### Protecting a local MCP server
383+
384+ Run a local MCP server and protect it with OIDC authentication:
385+
386+ ``` bash
387+ # Start your MCP server on localhost:8080
388+ # Then create a protected proxy
389+ thv proxy protected-mcp \
390+ --target-uri http://localhost:8080 \
391+ --port 3000 \
392+ --oidc-issuer https://auth.example.com \
393+ --oidc-audience mcp-users \
394+ --oidc-client-id mcp-proxy
395+ ```
396+
397+ Clients now connect to ` http://localhost:3000 ` with valid JWT tokens.
398+
399+ #### Accessing a protected remote MCP server
400+
401+ Connect to a remote MCP server that requires OAuth authentication:
402+
403+ ``` bash
404+ thv proxy remote-mcp \
405+ --target-uri https://api.example.com/mcp \
406+ --port 3000 \
407+ --remote-auth \
408+ --remote-auth-issuer https://auth.example.com \
409+ --remote-auth-client-id your-client-id \
410+ --remote-auth-client-secret-file /path/to/secret
411+ ```
412+
413+ Clients connect to ` http://localhost:3000 ` without handling OAuth flows.
414+
415+ #### Creating a secure gateway
416+
417+ Set up a secure gateway with authentication on both sides:
418+
419+ ``` bash
420+ thv proxy secure-gateway \
421+ --target-uri https://api.example.com/mcp \
422+ --port 3000 \
423+ --remote-auth \
424+ --remote-auth-issuer https://remote.example.com \
425+ --remote-auth-client-id remote-id \
426+ --remote-auth-client-secret-file /path/to/remote-secret \
427+ --oidc-issuer https://local.example.com \
428+ --oidc-audience gateway-users \
429+ --oidc-client-id gateway-proxy
430+ ```
431+
101432## Set up authorization
102433
103434ToolHive uses Amazon's Cedar policy language for fine-grained, secure-by-default
@@ -162,5 +493,3 @@ If you're having issues with the CLI:
162493- For detailed Cedar policy syntax, see
163494 [ Cedar policies] ( ../concepts/cedar-policies.md ) and the
164495 [ Cedar documentation] ( https://docs.cedarpolicy.com/ )
165- - For standalone proxy with authentication, see
166- [ Proxy with authentication] ( ./proxy-authentication.mdx )
0 commit comments