fix: allows for toggling non-auth users for MCP temp tokens - #3720
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds a persistent MCPEnableTempTokenAuth boolean and wires it through migrations, DB, transport schemas, Helm, UI, OAuth2 provider, and HTTP middleware to conditionally enable scoped temporary-token minting and validation for MCP per-user OAuth flows. ChangesMCP Temp-Token Auth Enablement Flag
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" 🔧 Trivy (0.69.3)Trivy execution failed: 2026-05-25T11:26:29Z FATAL Fatal error run error: fs scan error: scan error: scan failed: failed analysis: post analysis error: post analysis error: ansible scan error: fs filter error: fs filter error: walk error range error: stat .coderabbit-opengrep-fallback.yml: no such file or directory: range error: stat .coderabbit-opengrep-fallback.yml: no such file or directory Comment |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Confidence Score: 5/5Safe to merge; all gating paths (OAuth flow, auth middleware, UI toggle) are correctly wired and the flag defaults to false, preserving existing behavior. The core change is additive and well-contained: a new boolean flag that defaults to the safe value, backed by an atomic bool in AuthMiddleware and an atomic.Pointer in OAuth2Provider. DB migration is idempotent, the test covers all three states, and ReloadClientConfigFromConfigStore correctly propagates live config changes to AuthMiddleware. The only finding is a same-origin path-traversal gap in the new loginGoto validation helper, which is a hardening opportunity rather than an exploitable vulnerability in context. ui/lib/utils/loginGoto.ts — the isWorkspaceRoute check allows /workspace/../ traversal sequences; all other files look correct. Important Files Changed
Reviews (5): Last reviewed commit: "fix: allows for toggling non-auth users ..." | Re-trigger Greptile |
The merge-base changed after approval.
89b47ad to
63272c1
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ui/app/workspace/mcp-sessions/auth/page.tsx`:
- Around line 203-208: The "Log in instead" interactive control (the Button
asChild wrapping <a href={loginHref}> with the LogIn icon) is missing a
data-testid; add a stable data-testid to the interactive element (e.g.,
data-testid="login-instead-button") so E2E selectors can target it, and do the
same for the other newly added interactive Button at the other location
mentioned (lines 236-242) — if using Button asChild ensure the data-testid is
applied to the rendered DOM element (anchor) so tests see it.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c20c000e-f7ae-408c-815a-5c072638295a
📒 Files selected for processing (23)
framework/configstore/clientconfig.goframework/configstore/migrations.goframework/configstore/rdb.goframework/configstore/tables/clientconfig.goframework/oauth2/main.goframework/oauth2/sync_test.gohelm-charts/bifrost/templates/_helpers.tplhelm-charts/bifrost/values.schema.jsonhelm-charts/bifrost/values.yamltransports/bifrost-http/handlers/config.gotransports/bifrost-http/handlers/middlewares.gotransports/bifrost-http/handlers/session.gotransports/bifrost-http/lib/config.gotransports/bifrost-http/lib/config_test.gotransports/bifrost-http/server/server.gotransports/config.schema.jsontransports/schema_test/config_schema_test.goui/app/login/layout.tsxui/app/workspace/config/views/mcpView.tsxui/app/workspace/mcp-sessions/auth/page.tsxui/lib/store/apis/sessionApi.tsui/lib/types/config.tsui/lib/types/schemas.ts
✅ Files skipped from review due to trivial changes (1)
- helm-charts/bifrost/values.yaml
63272c1 to
8a4959a
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@transports/bifrost-http/handlers/session.go`:
- Around line 83-93: The endpoint currently maps auth_type using
authConfig.IsEnabled via dashboardAuthType(isEnabled) which only returns
"password" or "none" and never "sso"; change dashboardAuthType to derive its
return value from the actual configured auth mode (e.g. an authConfig.Mode or
authConfig.Type field) instead of IsEnabled, and update the call sites that pass
authConfig.IsEnabled to pass the real mode or the whole authConfig; implement
mapping to return "sso", "password", or "none" based on that mode and leave
existing behavior for backward-compatible values.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2ece0771-c06f-46cf-89c8-669db2293fb5
📒 Files selected for processing (24)
framework/configstore/clientconfig.goframework/configstore/migrations.goframework/configstore/rdb.goframework/configstore/tables/clientconfig.goframework/oauth2/main.goframework/oauth2/sync_test.gohelm-charts/bifrost/templates/_helpers.tplhelm-charts/bifrost/values.schema.jsonhelm-charts/bifrost/values.yamltransports/bifrost-http/handlers/config.gotransports/bifrost-http/handlers/middlewares.gotransports/bifrost-http/handlers/session.gotransports/bifrost-http/lib/config.gotransports/bifrost-http/lib/config_test.gotransports/bifrost-http/server/server.gotransports/config.schema.jsontransports/schema_test/config_schema_test.goui/app/login/layout.tsxui/app/workspace/config/views/mcpView.tsxui/app/workspace/mcp-sessions/auth/page.tsxui/lib/store/apis/sessionApi.tsui/lib/types/config.tsui/lib/types/schemas.tsui/lib/utils/loginGoto.ts
✅ Files skipped from review due to trivial changes (3)
- ui/lib/store/apis/sessionApi.ts
- transports/bifrost-http/lib/config_test.go
- helm-charts/bifrost/values.yaml
8a4959a to
bacaa5c
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@framework/oauth2/main.go`:
- Around line 69-74: tempTokenService currently uses p.mu.RLock which can get
blocked by long-running write locks; replace the lock-based access with an
atomic pointer to avoid stalls: add a field like tempTokensAtomic of type
atomic.Pointer[temptoken.Service], update all places that set p.tempTokens to
instead store via p.tempTokensAtomic.Store(newPtr), and change
tempTokenService() to return p.tempTokensAtomic.Load() (cast to
*temptoken.Service) without taking p.mu; ensure any nil checks still work. Use
sync/atomic.Pointer[temptoken.Service] (or atomic.Value) so readers don't
contend with refresh write locks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a2e2117c-6ed0-42ec-b89e-934a668f72de
📒 Files selected for processing (24)
framework/configstore/clientconfig.goframework/configstore/migrations.goframework/configstore/rdb.goframework/configstore/tables/clientconfig.goframework/oauth2/main.goframework/oauth2/sync_test.gohelm-charts/bifrost/templates/_helpers.tplhelm-charts/bifrost/values.schema.jsonhelm-charts/bifrost/values.yamltransports/bifrost-http/handlers/config.gotransports/bifrost-http/handlers/middlewares.gotransports/bifrost-http/handlers/session.gotransports/bifrost-http/lib/config.gotransports/bifrost-http/lib/config_test.gotransports/bifrost-http/server/server.gotransports/config.schema.jsontransports/schema_test/config_schema_test.goui/app/login/layout.tsxui/app/workspace/config/views/mcpView.tsxui/app/workspace/mcp-sessions/auth/page.tsxui/lib/store/apis/sessionApi.tsui/lib/types/config.tsui/lib/types/schemas.tsui/lib/utils/loginGoto.ts
✅ Files skipped from review due to trivial changes (1)
- ui/lib/types/config.ts
bacaa5c to
737f4d1
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ui/lib/utils/loginGoto.ts`:
- Around line 3-16: normalizeLoginGoto currently validates the raw input before
any path normalization, so inputs like "/workspace/../login" bypass the
allowlist; change the function to first resolve/normalize the input path (e.g.,
use a robust path/URL normalization method to collapse ".." and "." segments and
remove duplicate slashes) and then run the existing checks (isWorkspaceRoute, no
backslashes/newlines, no leading "//") against the normalized result, returning
null for anything that falls outside the intended /workspace prefix; apply the
same normalize-then-validate fix to the analogous logic at the other occurrence
(lines 23-29) so both locations validate the resolved path rather than the raw
string.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6c1816fc-79c3-4a8b-aee9-8c5b411474a5
📒 Files selected for processing (24)
framework/configstore/clientconfig.goframework/configstore/migrations.goframework/configstore/rdb.goframework/configstore/tables/clientconfig.goframework/oauth2/main.goframework/oauth2/sync_test.gohelm-charts/bifrost/templates/_helpers.tplhelm-charts/bifrost/values.schema.jsonhelm-charts/bifrost/values.yamltransports/bifrost-http/handlers/config.gotransports/bifrost-http/handlers/middlewares.gotransports/bifrost-http/handlers/session.gotransports/bifrost-http/lib/config.gotransports/bifrost-http/lib/config_test.gotransports/bifrost-http/server/server.gotransports/config.schema.jsontransports/schema_test/config_schema_test.goui/app/login/layout.tsxui/app/workspace/config/views/mcpView.tsxui/app/workspace/mcp-sessions/auth/page.tsxui/lib/store/apis/sessionApi.tsui/lib/types/config.tsui/lib/types/schemas.tsui/lib/utils/loginGoto.ts
✅ Files skipped from review due to trivial changes (2)
- ui/lib/store/apis/sessionApi.ts
- helm-charts/bifrost/values.yaml
Merge activity
|
## Summary Adds a new `mcp_enable_temp_token_auth` client config flag that gates whether Bifrost mints and accepts scoped short-lived temp tokens for MCP per-user OAuth authorization pages. Previously, temp-token auth was implicitly enabled whenever the `tempTokens` service was wired up. This change makes it an explicit opt-in, defaulting to `false`, so deployments must consciously enable it. ## Changes - Added `MCPEnableTempTokenAuth` bool field to `ClientConfig`, `TableClientConfig`, and all relevant migration/serialization paths, with a database migration to add the column. - `OAuth2Provider.InitiateUserOAuthFlow` now checks both that the `tempTokens` service is non-nil **and** that `MCPEnableTempTokenAuth` is `true` in client config before minting a temp token into the auth-page URL fragment. - `AuthMiddleware` gains a `tempTokensEnabled` atomic bool, initialized and updated via `ReloadClientConfigFromConfigStore`, so the `X-Bifrost-Temp-Token` fallback path in `tryTempTokenOrUnauthorized` is also gated by the same flag at runtime. - Added `UpdateTempTokenAuthEnabled` method on `AuthMiddleware` and wired it into `ReloadClientConfigFromConfigStore` so config changes take effect without a restart. - UI MCP settings view exposes a new "Allow Temp Token Auth Links" toggle, visible only when SSO/SCIM is enabled (`IS_ENTERPRISE && authType === "sso"`), with a descriptive label explaining the security trade-off. - Helm chart `_helpers.tpl`, `values.yaml`, and `values.schema.json` updated to expose `mcpEnableTempTokenAuth`. - `transports/config.schema.json` and the schema test updated to include `mcp_enable_temp_token_auth`. - Added `TestMCPTempTokenAuthEnabled` unit test covering the three states: no config, config with flag false, config with flag true. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test ```sh # Core/Transports go test ./framework/configstore/... ./framework/oauth2/... ./transports/bifrost-http/... # UI cd ui pnpm i pnpm build ``` **Manual validation:** 1. Start Bifrost with `mcp_enable_temp_token_auth: false` (default). Initiate a per-user MCP OAuth flow and confirm the returned auth-page URL contains **no** `#` fragment. 2. Set `mcp_enable_temp_token_auth: true`. Repeat the flow and confirm the URL contains a `#mcp_auth=<token>` fragment. 3. Confirm that after the flow completes or expires, the temp token is cleaned up and the fragment link no longer works. 4. In the UI (enterprise SSO deployment), navigate to MCP settings and verify the "Allow Temp Token Auth Links" toggle appears and persists correctly. **New config field:** | Field | Type | Default | Description | |---|---|---|---| | `mcp_enable_temp_token_auth` | `boolean` | `false` | When true, Bifrost mints and accepts scoped temp tokens for MCP per-user OAuth auth pages | ## Breaking changes - [x] No The flag defaults to `false`, preserving existing behavior. Deployments that previously relied on temp-token auth being implicitly active (when the service was wired) must explicitly set `mcp_enable_temp_token_auth: true`. ## Security considerations Temp tokens embedded in URL fragments grant unauthenticated access to a specific MCP OAuth flow page for the lifetime of the flow. Keeping this opt-in (`false` by default) ensures operators consciously accept this trade-off. The tokens are scoped to a single `session_id` resource and are deleted on flow completion or expiry. The feature is surfaced in the UI only for SSO-enabled enterprise deployments where per-user OAuth flows are most relevant. ## Checklist - [x] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [ ] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
## ✨ Features
- **Azure v1 API Migration** — Migrated Azure provider to the v1 API:
removed the `api-version` query parameter and the
`/openai/deployments/{model}/...` URL pattern in favor of
`/openai/v1/{operation}`; the `api_version` field has been dropped from
`AzureKeyConfig` (#3661, #3756)
- **EnvVar Support for OTEL & Prometheus Configs** — `CollectorURL`,
`MetricsEndpoint`, headers, push gateway URL, and basic auth credentials
can now be sourced from environment variables (e.g.,
`env.OTEL_COLLECTOR_URL`); added a new `ConfigMarshallerPlugin`
interface that lets plugins control storage/redaction round-trips
(#3651)
- **OTel Extra Header Forwarding** — `x-bf-eh-*` extra headers forwarded
to upstream providers are now also emitted on the request span under
`gen_ai.request.extra_header.*` for end-to-end tracing (#3730)
- **OTel Semantic Conventions** — Aligned OTel attribute keys with the
OpenTelemetry GenAI spec (canonical `gen_ai.*` and new `bifrost.*`
attributes); legacy attributes are retained in parallel to avoid
breaking existing dashboards (#3732)
- **VK Quota with Provider Configs** — `GetVirtualKeyQuotaByValue` and
the `getVirtualKeyQuota` HTTP response now include `provider_configs`
with their budgets and rate limits (#3721)
- **MCP Temp Token Non-Auth Toggle** — Added
`mcp_enable_temp_token_auth` client config flag to gate short-lived MCP
token minting for non-authenticated users (#3720)
- **Responses Stream in JSON Parser** — `jsonparser` plugin now handles
OpenAI Responses API streaming (`ResponsesStreamRequest`) in addition to
chat completions (#3749)
- **Session API Rework** — Logout now calls both the password-based
session logout and OAuth logout endpoints and resets all RTK Query cache
state (#3698)
## 🐞 Fixed
- **Streaming Latency for Observability** — Deferred root span
termination to the trace completer callback for streaming requests so
request latency is no longer inflated by header-flush time (#3762)
- **Stream Cancellation Race** — Set `BifrostContextKeyConnectionClosed`
before closing the stream and short-circuit `idleTimeoutReader.Read`
when the connection is already closed to avoid panics and hangs on
cancellation (#3733)
- **Bedrock Cache Points** — Strip cache points from Bedrock requests
for models that do not support prompt caching (e.g., GLM, Llama) to
avoid Converse API errors (#3754)
- **Bedrock Empty Text Blocks** — Skip empty/nil text blocks during
Bedrock response conversion to avoid invalid messages (#3747)
- **Bedrock Reasoning + Tools** — Preserve reasoning content blocks on
assistant turns that also contain tool calls in the Bedrock chat
converter (#3690)
- **Bedrock Search Content & Video** — Restored search content and video
parts that were being dropped from Bedrock-native passthrough requests
(#3729)
- **Structured Output Stop Reason** — Fixed an incorrect `tool_calls`
finish reason when structured output is combined with extended-thinking
tools (#3685)
- **Gemini Tool Schema Passthrough** — Forward full tool parameter
schemas via `parametersJsonSchema` instead of the lossy `parameters`
form; corrected tool response role to `user`; resolved structured output
+ tools conflict (#3761)
- **Anthropic Stop Reason & Tool Versions** — Normalized stop reason
mapping (`end_turn` to `stop`, `tool_use` to `tool_calls`, `max_tokens`
to `length`) and upgraded `text_editor_20250124`/`str_replace_editor` to
`text_editor_20250728` for computer-use tools (#3761)
- **Azure Endpoint Redaction** — Fixed a panic when
`AzureKeyConfig.Endpoint` is a literal value rather than an env
reference (#3761)
- **Auth Middleware Path Match** — Match temp-token auth middleware
whitelist against the request path only, not the full URI with query
parameters (#3737)
- **Governance Blocked Models UI** — Restored the missing Blocked Models
create/edit UI in the VK provider config sheet (#3750)
- **Logging Plugin Cleanup Drain** — Fixed a shutdown race where
`batchWriter` could drop in-flight log entries; `Cleanup` now drains
both the recovered batch and remaining queue within a 30-second budget
(#3717)
- **Model Rankings Empty Entries** — Excluded entries with empty `model`
values from model rankings matview queries so blank rows no longer
surface in the UI (#3758)
- **User Filter Duplicates** — Recreated `mv_filter_users` matview to
require non-empty `user_name`, eliminating duplicate filter dropdown
entries (#3764)
- **User Filter Display Name** — Use `user_name` instead of `user_id` as
the display label for users in logging filters (#3691)
- **Large Numeric ID Precision** — Preserve large numeric IDs in URL
search params by skipping JSON parsing for plain strings (#3692)
## 🔧 Refactors & Chores
- **Error Propagation for GetAvailable\* APIs** — `GetAvailable*`
methods on `LoggerPlugin`/`LogManager` now return wrapped errors instead
of silently logging and returning empty slices (#3759)
- **Governance Blocklist Matching** — Use `slices.Contains` for VK
blocked-model matching for clearer code with identical semantics (#3727)
- **Exported `ResolvePeriod`** — Renamed `resolvePeriod` to
`ResolvePeriod` so external packages can reuse the period parsing
(#3763)
## 📚 Docs
- **OTEL Env Var Documentation** — Documented `env.VAR_NAME` support for
`collector_url`, `metrics_endpoint`, and headers in OTEL/Prometheus
plugin docs
- **OTEL OSS Features & Examples** — Added OTEL documentation to the OSS
features list with usage examples (#3731)
- **Anthropic Auth Recommendation** — Recommend `ANTHROPIC_AUTH_TOKEN`
over `ANTHROPIC_CUSTOM_HEADERS` for Claude Code authentication (#3686)
## Summary
This PR releases Bifrost OSS `v1.5.5` and Enterprise `v1.4.4`, bumping all module pins from `v1.5.12`/`v1.3.12` to `v1.5.13`/`v1.3.13` across core, framework, and all plugins. It also hardens the Docker manifest shell scripts, expands CI egress allowlists, and updates documentation to reflect the new SCIM-based user provisioning feature.
## Changes
- **Module version bumps**: All `go.mod`/`go.sum` files updated from `core v1.5.12` → `v1.5.13`, `framework v1.3.12` → `v1.3.13`, and all plugin versions incremented accordingly (`compat`, `governance`, `jsonparser`, `logging`, `maxim`, `mocker`, `otel`, `prompts`, `semanticcache`, `telemetry`).
- **Docker manifest scripts**: Added `#!/usr/bin/env bash` shebang and `set -euo pipefail` to `create-docker-manifest.sh` and `create-docker-manifest-ubi9.sh`; quoted all variable expansions and switched `jq -r` to `jq -er` to fail on null digests.
- **CI egress allowlist**: Added `production.cloudfront.docker.com:443` to Docker-related job allowlists, and added `_https._tcp.dl.google.com:443` and `motd.ubuntu.com:443` to the Ubuntu package job allowlist.
- **Changelog files**: Cleared per-module `changelog.md` files (content moved into the new versioned docs). Added `docs/changelogs/v1.5.5.mdx` and `docs/changelogs/ent-v1.4.4.mdx` with full release notes, and registered both in `docs/docs.json`.
- **Documentation**: Replaced the SSO Integration link with a User Provisioning (SCIM) link in both `README.md` and `transports/README.md`.
- **Enterprise v1.4.4 highlights** (documented): Kafka and Google Cloud Pub/Sub observability sinks, chunked streaming with a 100 MB inter-node message ceiling, BigQuery custom labels via env vars using the new `ConfigMarshallerPlugin` interface, temporary access token expiry extensions, and a multi-node cluster integration harness.
- **OSS v1.5.5 highlights** (documented): Azure v1 API migration, env-var support for OTel/Prometheus configs, OTel extra-header forwarding and semantic-convention alignment, virtual key quota including provider configs, Responses API streaming in `jsonparser`, and a batch of Bedrock, Gemini, Anthropic, Azure, and logging plugin fixes.
## Type of change
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [x] Documentation
- [x] Chore/CI
## Affected areas
- [x] Core (Go)
- [x] Transports (HTTP)
- [x] Providers/Integrations
- [x] Plugins
- [ ] UI (React)
- [x] Docs
## How to test
```sh
# Core/Transports
go version
go test ./...
# Verify Docker manifest scripts exit on error
bash -n .github/workflows/scripts/create-docker-manifest.sh
bash -n .github/workflows/scripts/create-docker-manifest-ubi9.sh
```
Validate that the new changelog pages (`changelogs/v1.5.5` and `changelogs/ent-v1.4.4`) render correctly in the docs site.
## Screenshots/Recordings
N/A
## Breaking changes
- [x] Yes
- [ ] No
The Azure provider no longer accepts `api_version` in `AzureKeyConfig` and has migrated to the `/openai/v1/{operation}` URL pattern. See the [v1.4.0 Migration Guide](https://docs.getbifrost.ai/enterprise/migration-guides/v1.4.0) for full details.
## Related issues
#3661, #3756, #3651, #3730, #3732, #3754, #3747, #3690, #3729, #3685, #3733, #3761, #3735, #3721, #3720, #3749, #3698, #3762, #3750, #3727, #3717, #3759, #3758, #3764, #3691, #3692, #3737, #3763
## Security considerations
- The `ConfigMarshallerPlugin` interface redacts secrets (OTel collector URLs, Prometheus push gateway credentials, BigQuery labels) at config storage time and rehydrates them at load time, preventing plaintext secret persistence.
- Docker manifest scripts now use `set -euo pipefail`, preventing silent failures that could result in malformed or missing image manifests being pushed.
## Checklist
- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

Summary
Adds a new
mcp_enable_temp_token_authclient config flag that gates whether Bifrost mints and accepts scoped short-lived temp tokens for MCP per-user OAuth authorization pages. Previously, temp-token auth was implicitly enabled whenever thetempTokensservice was wired up. This change makes it an explicit opt-in, defaulting tofalse, so deployments must consciously enable it.Changes
MCPEnableTempTokenAuthbool field toClientConfig,TableClientConfig, and all relevant migration/serialization paths, with a database migration to add the column.OAuth2Provider.InitiateUserOAuthFlownow checks both that thetempTokensservice is non-nil and thatMCPEnableTempTokenAuthistruein client config before minting a temp token into the auth-page URL fragment.AuthMiddlewaregains atempTokensEnabledatomic bool, initialized and updated viaReloadClientConfigFromConfigStore, so theX-Bifrost-Temp-Tokenfallback path intryTempTokenOrUnauthorizedis also gated by the same flag at runtime.UpdateTempTokenAuthEnabledmethod onAuthMiddlewareand wired it intoReloadClientConfigFromConfigStoreso config changes take effect without a restart.IS_ENTERPRISE && authType === "sso"), with a descriptive label explaining the security trade-off._helpers.tpl,values.yaml, andvalues.schema.jsonupdated to exposemcpEnableTempTokenAuth.transports/config.schema.jsonand the schema test updated to includemcp_enable_temp_token_auth.TestMCPTempTokenAuthEnabledunit test covering the three states: no config, config with flag false, config with flag true.Type of change
Affected areas
How to test
Manual validation:
mcp_enable_temp_token_auth: false(default). Initiate a per-user MCP OAuth flow and confirm the returned auth-page URL contains no#fragment.mcp_enable_temp_token_auth: true. Repeat the flow and confirm the URL contains a#mcp_auth=<token>fragment.New config field:
mcp_enable_temp_token_authbooleanfalseBreaking changes
The flag defaults to
false, preserving existing behavior. Deployments that previously relied on temp-token auth being implicitly active (when the service was wired) must explicitly setmcp_enable_temp_token_auth: true.Security considerations
Temp tokens embedded in URL fragments grant unauthenticated access to a specific MCP OAuth flow page for the lifetime of the flow. Keeping this opt-in (
falseby default) ensures operators consciously accept this trade-off. The tokens are scoped to a singlesession_idresource and are deleted on flow completion or expiry. The feature is surfaced in the UI only for SSO-enabled enterprise deployments where per-user OAuth flows are most relevant.Checklist
docs/contributing/README.mdand followed the guidelines