feat: run the VeADK web UI behind a key-auth API gateway (+ SSO AgentKit example)#610
Merged
Merged
Conversation
Deploy the VeADK web UI together with VeIdentity SSO to an AgentKit runtime. The self-contained app.py serves the bundled UI + agent API behind VeIdentity OAuth2, with two adaptations for the AgentKit gateway: - strips the gateway key from the Authorization header before the SSO middleware runs, so SSO falls back to its session cookie instead of failing with "Invalid JWT format" (the gateway forwards its key in Authorization, which the middleware would otherwise try to decode as a user JWT); - forwards the page querystring onto /assets/* URLs, for gateways configured to take the key from the query string. Runs on stock veadk-python>=0.5.39. Bilingual README with paste-able deploy commands (config -> launch -> set callback -> deploy -> add header in browser).
Two changes so `veadk frontend` works behind a gateway (e.g. an AgentKit runtime) that authenticates every request with a key and forwards the Authorization header to the app: - cli_frontend: when serving the built UI, forward the page's querystring onto the /assets/* URLs, so a browser behind a query-string gateway carries the key on subresource requests too. Assets are mounted explicitly and a SPA fallback renders the injected shell, registered after the API routes. - oauth2 middleware: ignore a non-JWT Authorization bearer (unless token introspection is enabled) so authentication falls back to the session cookie instead of failing with "Invalid JWT format" when the gateway puts its opaque key in Authorization. A genuine user JWT is left untouched.
Replace the interactive `veadk agentkit config` step with the non-interactive flag form (account-specific fields auto-create when omitted; runtime_envs are merged), so the whole deploy is copy-paste: config -> launch -> set the callback -> deploy. Note that the gateway adaptations are built into `veadk frontend` from the next release.
298c7b8 to
7adaa53
Compare
Only the two VeIdentity UIDs (OAUTH2_USER_POOL_ID / OAUTH2_USER_POOL_CLIENT_ID, which hold the pool/client UIDs) go into --runtime_envs. Drop MODEL_AGENT_* (the model is provided by the runtime) and the Volcengine AK/SK (the runtime uses its service-role credentials for the VeIdentity API; AK/SK stay in .env only for the local build & deploy). Also explain why OAUTH2_REDIRECT_URI is needed on the runtime but not locally.
Verified end-to-end against an AgentKit runtime: the runtime has no usable role credentials (the instance-metadata endpoint times out), so VeIdentity API calls need AK/SK explicitly. Without them the container crashes on startup with "User pool ... not found". Put VOLCENGINE_ACCESS_KEY/SECRET_KEY back into the config command and fix the surrounding notes. The model stays out of runtime_envs (the UI serves without it; the agent loads lazily).
zakahan
approved these changes
Jun 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes the VeADK web UI work behind an API gateway that authenticates every request with a key, and adds a deployable example for VeADK web UI + VeIdentity SSO on an AgentKit runtime.
Framework
The AgentKit gateway puts the runtime key in
Authorization: Bearer <key>and forwards that header to the app, which collides with VeADK's own auth. Two fixes soveadk frontendworks behind it:veadk/cli/cli_frontend.py— when serving the built UI, forward the page's querystring onto/assets/*URLs, so a browser behind a query-string gateway carries the key on subresource requests too. Assets are mounted explicitly; a SPA fallback renders the injected shell, registered after the API routes.veadk/auth/middleware/oauth2_auth.py— ignore a non-JWTAuthorizationbearer (unless token introspection is enabled) so auth falls back to the session cookie instead of failing withInvalid JWT formatwhen a header gateway forwards its opaque key. A genuine user JWT is untouched.Example:
examples/sso_frontend_on_agentkit/app.py— self-contained: serves the bundled UI + ADK agent API behind VeIdentity OAuth2. Self-contains the two adaptations above so it runs on the releasedveadk-python>=0.5.39(the framework fixes above land them inveadk frontendfor the next release).agents/sso_demo_agent/,requirements.txt,.env.example,.dockerignore.README.zh.md+README.md— fully non-interactive, copy-paste deploy: non-interactiveveadk agentkit config(account fields auto-create;runtime_envsmerge) →launch→ set callback →deploy.Access note
The runtime key currently only supports the header location (
CreateRuntime'sApiKeyLocationaccepts onlyheader), so browser access uses a header-injecting extension (e.g. ModHeader) — documented in the README.Test plan
ruff check/ruff format --checkclean on changed files; no newpyrighterrors (the 4 reported are pre-existing).markdownlintclean on both READMEs.veadk frontend(both framework fixes):/?gw=...injects the querystring into asset URLs;/list-appswith a non-JWTAuthorizationreturns 302 (login) instead ofInvalid JWT format; a 3-part JWT is still validated as a user token.veadk agentkit configverified to run without prompts and write a validagentkit.yaml./,/web/auth-config,/oauth2/login(302 to the user pool), assets, and post-login/list-appsall verified.🤖 Generated with Claude Code