Commit bc9b534
fix: oauth issues and add tokenResponseMapping for non-standard providers (#4009)
* Fix TOOLHIVE_DEBUG env var not enabling debug logging
The logger was initialized in main.go before viper.BindEnv was called
in commands.go, so TOOLHIVE_DEBUG had no effect on log level. Move the
env var binding before the logger initialization.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Propagate upstream user name and email into JWT claims
The embedded auth server resolved user identity (name, email) from the
upstream IDP via the userInfo endpoint but only stored the subject
claim in the JWT. This caused audit logs to show "anonymous" for the
user field despite successful authentication.
Propagate name and email from the upstream Identity through to the
session's JWT claims as standard OIDC claims (name, email per OIDC
Core Section 5.1). The auth middleware's claimsToIdentity function
already reads these claims, so the audit middleware will now display
the actual user name.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix remote URL path not forwarded to backend server
When the remote URL has a path (e.g., https://mcp.asana.com/v2/mcp),
the proxy stripped it and only used the scheme+host as the target.
Client requests to /mcp were forwarded to https://mcp.asana.com/mcp
instead of https://mcp.asana.com/v2/mcp, causing Asana to return
401 invalid_token because the endpoint doesn't exist at /mcp.
Extract the remote URL's path and pass it to the transparent proxy
via WithRemoteBasePath. The proxy's Director rewrites incoming
request paths to the remote server's configured path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add tokenResponseMapping for non-standard OAuth token responses
Some OAuth providers (e.g., GovSlack) nest token fields under
non-standard paths instead of returning them at the top level.
GovSlack returns access_token under authed_user.access_token,
causing the standard oauth2 library to fail with "response missing
access_token".
Add a tokenResponseMapping field to OAuth2UpstreamConfig that
configures dot-notation paths for extracting token fields from
non-standard response formats. When set, the token exchange bypasses
golang.org/x/oauth2 and makes the HTTP POST directly, extracting
fields using gjson (already a dependency).
Example usage:
tokenResponseMapping:
accessTokenPath: "authed_user.access_token"
tokenTypePath: "authed_user.token_type"
Changes span the full config pipeline: CRD types, RunConfig,
operator conversion, runtime resolution, and the upstream provider.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Regenerate CRD manifests and docs for tokenResponseMapping
Run `task operator-manifests` and `crd-ref-docs` to update the
CRD schema with the new tokenResponseMapping field on
OAuth2UpstreamConfig and regenerate the API reference docs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update image build dependencies and fix run-on-main workflow
* Normalize token_type to Bearer in token response rewriter
GovSlack returns token_type "user" which the oauth2 library rejects
since it only accepts "Bearer". Since the rewriter already handles
non-standard responses, always normalize token_type to "Bearer" so
the oauth2 library accepts it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: respond to reviewer
* chore: fixing debug env usage in thv cli
* fix: regenerated swag docs
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent ff81ee4 commit bc9b534
29 files changed
Lines changed: 1047 additions & 34 deletions
File tree
- cmd
- thv-operator
- api/v1alpha1
- pkg/controllerutil
- thv-proxyrunner
- thv
- deploy/charts/operator-crds
- files/crds
- templates
- docs
- operator
- server
- pkg
- authserver
- runner
- server
- handlers
- session
- storage
- upstream
- transport
- proxy/transparent
Lines changed: 34 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
331 | 331 | | |
332 | 332 | | |
333 | 333 | | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
334 | 368 | | |
335 | 369 | | |
336 | 370 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
519 | 519 | | |
520 | 520 | | |
521 | 521 | | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
522 | 531 | | |
523 | 532 | | |
524 | 533 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
18 | 25 | | |
19 | 26 | | |
20 | 27 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
26 | 33 | | |
27 | 34 | | |
28 | 35 | | |
| |||
Lines changed: 32 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
441 | 441 | | |
442 | 442 | | |
443 | 443 | | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
444 | 476 | | |
445 | 477 | | |
446 | 478 | | |
| |||
Lines changed: 32 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
444 | 444 | | |
445 | 445 | | |
446 | 446 | | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
447 | 479 | | |
448 | 480 | | |
449 | 481 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments