fix(ui): forward incoming auth headers in webpack dev proxy#2544
Conversation
The webpack dev server's proxy was capturing the kubeconfig token at startup and setting it as a static header, which overwrote any auth headers forwarded by a host backend proxy (e.g. ODH Dashboard with dev impersonation). Switch to an onProxyReq callback that dynamically forwards incoming authorization headers when present and falls back to the kubeconfig token for standalone dev mode. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Mike Turley <mike.turley@alum.cs.umass.edu>
|
/retest-required |
|
Hi @mturley! I've been tackling the same issue across all BFF-backed modules in the ODH Dashboard monorepo (see opendatahub-io/odh-dashboard#7372) after I saw your thread. I tested the fix on a live cluster with both maas and model-registry BFFs and confirmed impersonation token forwarding works end-to-end. I wanted to share our approach since we applied the same pattern to 6 other modules (maas, gen-ai, automl, autorag, mlflow, eval-hub) and it'd be great to keep consistency across all of them. Our approach is a bit simpler — here's the key difference: Your current approach
Our approach (applied to 6 modules)
proxy: [
{
context: ['/api', '/model-registry/api'],
target: { host: PROXY_HOST, protocol: PROXY_PROTOCOL, port: PROXY_PORT },
changeOrigin: true,
onProxyReq: (proxyReq, req) => {
const upstreamAuth = req.headers.authorization;
if (upstreamAuth && AUTH_METHOD === 'user_token') {
// Federated mode: forward the upstream token (may be impersonated) as x-forwarded-access-token
const token = upstreamAuth.replace(/^Bearer\s+/i, '');
proxyReq.setHeader('x-forwarded-access-token', token);
} else {
// Standalone / internal auth: use the static headers from getProxyHeaders()
const headers = getProxyHeaders();
Object.entries(headers).forEach(([key, value]) => {
proxyReq.setHeader(key, value);
});
}
},
},
],Why this is simpler
Also: pre-existing lint issuesWhen we ran our lint hooks against the downstream copy of this file, we hit pre-existing errors that needed fixing:
You might want to fix those here too since they'll come up once the downstream sync happens. Happy to discuss if you have questions about the approach! |
Replace static `headers: getProxyHeaders()` with `onProxyReq` callback in all module webpack dev proxies. In federated mode, the main dashboard backend sets the authorization header (which may carry an impersonated token). The new callback extracts it and forwards as x-forwarded-access-token for the BFF, matching production convention. In standalone/internal auth modes, falls back to getProxyHeaders(). model-registry is excluded — handled upstream via kubeflow/hub#2544.
|
Thanks @lucferbux ! This approach does make more sense. I'm on PTO this week, I can replace this PR when I get back or if you want us to merge sooner for consistency someone else on our scrum could do it. |
|
@mturley after re-evaluating, your solution is fine, it's doing an extra step, I misread your thread and I thought you didn't get the full solution for all modules, we can keep your solution as it's already stablished, approving and merging |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: lucferbux The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
/retest |
|
Thanks @lucferbux ! |
Description
The webpack dev server's proxy was capturing the kubeconfig token at startup and setting it as a static
headersconfig, which overwrote any auth headers forwarded by a host backend proxy (e.g. ODH Dashboard with dev impersonation). This meant that when running in federated mode withAUTH_METHOD=user_token, the BFF always operated with admin-level permissions regardless of which user the host backend was impersonating.This PR switches to an
onProxyReqcallback that dynamically forwards incomingauthorizationheaders when present, and falls back to the kubeconfig token captured at startup for standalone dev mode. This preserves the existing standalone behavior while enabling proper auth forwarding for federated setups.Before
getProxyHeaders()rankubectl config viewat startup and returned staticAuthorizationandx-forwarded-access-tokenheadersAfter
getKubeconfigToken()captures the kubeconfig token at startup as a fallbackgetProxyHeaders()returns{}foruser_tokenmode (no static auth headers)onProxyReqcallback dynamically:authorizationheader if present (federated mode with impersonation)How Has This Been Tested?
Manual testing with ODH Dashboard federated dev mode:
DEV_IMPERSONATE_USERconfiguredMerge criteria:
DCOcheck)ok-to-testhas been added to the PR.If you have UI changes