Skip to content

Inject OBO access token in apps run-local#5795

Open
ZaSkittles wants to merge 1 commit into
databricks:mainfrom
ZaSkittles:zack-loebel/apps-run-local-obo-token
Open

Inject OBO access token in apps run-local#5795
ZaSkittles wants to merge 1 commit into
databricks:mainfrom
ZaSkittles:zack-loebel/apps-run-local-obo-token

Conversation

@ZaSkittles

@ZaSkittles ZaSkittles commented Jul 2, 2026

Copy link
Copy Markdown

What did you change, and why?

databricks apps run-local starts a local proxy that fronts the app and
injects the identity headers the deployed Apps OAuth2 proxy would
(X-Forwarded-Email, X-Forwarded-User, ...) — but not
X-Forwarded-Access-Token. That token is the on-behalf-of (OBO) credential
the deployed platform forwards so an app can call Databricks APIs as the
calling user. Locally it is simply absent, so every OBO code path sees the
header as missing and fails, and OBO-gated surfaces can't be exercised in a
browser without deploying.

This injects X-Forwarded-Access-Token too, minted from the CLI's own
credentials (the same profile already used for CurrentUser.Me), matching
the deployed proxy.

  • libs/appproxy: add InjectHeaderFunc(key, fn) for a header whose value is
    resolved per request. Used for the token because it expires: the SDK token
    source returns a cached token without blocking in the steady state and
    refreshes on demand, so a browser session that outlives a single token keeps
    working. A resolution error fails the request with 502 rather than
    forwarding it without the header. Both the HTTP and WebSocket paths now go
    through a shared applyInjectedHeaders.
  • cmd/apps/run_local.go: inject the token from w.Config.GetTokenSource(),
    mirroring the existing idiom in cmd/apps/logs.go.
  • libs/apps/runlocal: export the header name as a constant.

How do you know it works?

Unit tests cover the new InjectHeaderFunc (per-request resolution + the
502-on-error path). Manually verified end-to-end against a Lakehouse App: a
request straight to the app returns 401 (OBO fails, as before), while the same
request through the run-local proxy returns 200 with OBO-backed pages
rendering as the calling user.

The deployed Apps platform fronts each slot with an OAuth2 proxy that
injects the caller's on-behalf-of (OBO) token as X-Forwarded-Access-Token.
`databricks apps run-local` starts a local proxy that injects the identity
headers (X-Forwarded-Email, etc.) but not the token, so OBO code paths
can't be exercised locally — the app sees the header as missing and every
OBO route fails.

Mint a token from the CLI's own credentials (the same profile already used
for CurrentUser.Me) and inject it as X-Forwarded-Access-Token. The value is
resolved per request via a new appproxy InjectHeaderFunc so a browser
session outliving a single token still gets a refreshed one; the SDK token
source returns a cached token without blocking in the steady state. A
resolution failure fails the request with 502 rather than forwarding it
without the header.

Co-authored-by: Isaac
@ZaSkittles ZaSkittles force-pushed the zack-loebel/apps-run-local-obo-token branch from f7263cb to 1c6609e Compare July 2, 2026 03:49
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

An authorized user can trigger integration tests manually by following the instructions below:

Trigger:
go/deco-tests-run/cli

Inputs:

  • PR number: 5795
  • Commit SHA: 1c6609e0d7a445868208e8c1082a78f3801d1b53

Checks will be approved automatically on success.

@ZaSkittles ZaSkittles marked this pull request as ready for review July 2, 2026 03:56
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Approval status: pending

/cmd/apps/ - needs approval

Files: cmd/apps/run_local.go, cmd/apps/run_local_test.go
Suggested: @MarioCadenas
Also eligible: @fjakobs, @Shridhad, @atilafassina, @keugenek, @igrekun, @pkosiec, @pffigueiredo, @ditadi, @calvarjorge

/libs/apps/ - needs approval

Files: libs/apps/runlocal/headers.go
Suggested: @MarioCadenas
Also eligible: @fjakobs, @Shridhad, @atilafassina, @keugenek, @igrekun, @pkosiec, @pffigueiredo, @ditadi, @calvarjorge

General files (require maintainer)

Files: NEXT_CHANGELOG.md, libs/appproxy/appproxy.go, libs/appproxy/appproxy_test.go
Based on git history:

  • @simonfaltum -- recent work in ./, cmd/apps/, libs/appproxy/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db) can approve all areas.
See OWNERS for ownership rules.

@theof-db theof-db left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you able to test this e2e locally?

@ZaSkittles

Copy link
Copy Markdown
Author

Were you able to test this e2e locally?

yes! I was able to run it against my app locally and see the token forwarded to my app. I wrote a note about this in the how it works section

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants