feat: add configurable OIDC authentication for enterprise deployments#442
Open
rrbanda wants to merge 10 commits into
Open
feat: add configurable OIDC authentication for enterprise deployments#442rrbanda wants to merge 10 commits into
rrbanda wants to merge 10 commits into
Conversation
…ployments Adds optional OIDC authentication support to ADK Web UI, enabling enterprise deployments where agents are managed by Kagenti with SPIFFE/SPIRE zero-trust security. When auth.enabled is true in runtime-config.json (or injected via window.__ADK_CONFIG__ ConfigMap), users must authenticate via an OIDC provider before accessing the UI. When disabled (default), behavior is unchanged. Key changes: - Add AuthConfig to RuntimeConfig model - Add AuthService (keycloak-js) for OIDC lifecycle management - Add AuthInterceptor to attach Bearer tokens to API requests - Add AuthGuard for route protection - Add runtime config resolution (ConfigMap + runtime-config.json) - Add AuthUserMenuComponent showing authenticated user info + logout - Wire up APP_INITIALIZER and HTTP_INTERCEPTORS in main.ts - Add silent-check-sso.html for background token refresh Design principles: - Opt-in: auth disabled by default, zero impact on existing users - Provider-agnostic: standard OIDC, works with Keycloak/Okta/Auth0 - Runtime-configurable: enable via ConfigMap without rebuilding - Zero backend changes: auth enforced at UI + interceptor level
…nent The component template uses <app-markdown> but the class was imported without being added to the @component imports array, causing build failures.
The AuthInterceptor only covers Angular HttpClient requests, but the SSE streaming endpoint (run_sse) uses raw fetch() and WebSocket connections bypass HttpClient entirely. Without this fix, Kagenti's Envoy AuthBridge would reject these requests when OIDC auth is enabled. - AgentService.runSse: inject AuthService, get token before fetch, add Authorization header to SSE requests - WebSocketService.connect: inject AuthService, append token as query parameter (standard WS auth pattern since browser WebSocket API doesn't support custom headers) - Update WebSocketService interface for async connect signature
Critical fixes: - Replace keycloak-js with oidc-client-ts for provider-agnostic OIDC support (works with Keycloak, Okta, Auth0, Azure AD, any OIDC provider) - Remove WebSocket token-from-query-string (log/referrer leakage risk); document as known limitation requiring server-side protocol changes Major fixes: - Make AuthService.init() idempotent (deduplicate concurrent calls) - Fail-closed: block requests when auth enabled but token missing, instead of sending unauthenticated requests - Fix getToken() to propagate refresh failures and trigger re-login - Add SSE response.ok check before reading stream body - Improve auth guard: redirect to login instead of blank page - Handle bootstrap auth failure with visible error state - Migrate to Angular 21 APIs: provideAppInitializer (replaces deprecated APP_INITIALIZER), functional interceptor (replaces class-based HTTP_INTERCEPTORS), provideHttpClient Minor fixes: - Add Window augmentation for __ADK_CONFIG__ (removes any casts) - Export UserInfo as type from barrel - Wire scopes config through to OIDC client - Add Apache 2.0 license headers to all new files - Consistent copyright year (2025) Testing: - Add Karma/Jasmine specs for auth.service, auth.interceptor, auth.guard, auth.config, and user-menu component - Tests follow existing initTestBed() pattern for 1p compatibility Documentation: - Add Authentication section to README covering OIDC setup, Kubernetes ConfigMap injection, Kagenti/SPIFFE integration, supported providers, and security model
Includes: - ConfigMap for runtime auth config (OIDC authority, clientId) - Deployment with nginx serving the SPA + API reverse proxy - nginx config with SPA fallback, API proxy, security headers - Service and Route with TLS edge termination - Dockerfile for multi-stage production build Auth is configurable via ConfigMap -- update authority/clientId and restart the pod. No image rebuild needed.
- Use sed to rewrite pid path to /tmp/nginx.pid (writable by non-root) - Remove 'user nginx' directive for arbitrary UID compatibility - Extract nginx.conf to separate file for ConfigMap override - Set non-root USER 101 for OpenShift restricted SCC
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
- Fix deploy/openshift.yaml: use quay.io/rbrhssa/adk-web:latest image instead of nginx:1.27-alpine + emptyDir, add imagePullSecrets, add proxy_read_timeout 300s for SSE, add OIDC provider format comments - Add to README: step-by-step OpenShift deployment with oc commands, Keycloak client creation guide, and demo test prompts for both F5 provisioning and branch monitoring use cases
OpenShift deployment manifests (Dockerfile, nginx config, K8s YAML) are infrastructure-specific and should not be in the core repo. Users deploy according to their own platform. The deploy files remain available in the rrbanda/adk-web fork for reference.
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.
Summary
Adds optional, provider-agnostic OIDC authentication to ADK Web UI for enterprise deployments where agents are managed by platforms like Kagenti with SPIFFE/SPIRE zero-trust security.
oidc-client-ts(standard OIDC). Works with Keycloak, Okta, Auth0, Azure AD, or any OIDC-compliant provider.runtime-config.jsonor Kubernetes ConfigMap -- no image rebuild needed.provideAppInitializer, functional interceptor viaprovideHttpClient(withInterceptors([...])), functional route guard.New files
src/app/core/auth/-- AuthService (oidc-client-ts UserManager), functional HTTP interceptor, route guard, config resolver with Window type augmentationsrc/app/components/user-menu/-- Authenticated user menu component (name, email, roles from JWT, logout)src/silent-check-sso.html-- Silent token refresh for background renewaldeploy/-- Dockerfile (multi-stage, non-root nginx) and OpenShift manifests with ConfigMap-based auth configinitTestBed()patternModified files
src/main.ts--provideAppInitializerfor auth init,provideHttpClientwith functional interceptor, visible error on bootstrap failuresrc/app/app-routing.module.ts-- Auth guard on root routesrc/app/components/chat/-- Conditionally show auth user menu vs original user ID editorsrc/app/core/services/agent.service.ts-- Bearer token on SSE fetch,response.okcheck before reading streamsrc/app/core/models/RuntimeConfig.ts--AuthConfiginterface (authority, clientId, scopes)README.md-- Authentication section with setup guide, supported providers, ConfigMap injection, Kagenti/SPIFFE integrationConfiguration example
{ "backendUrl": "http://localhost:8000", "auth": { "enabled": true, "authority": "https://keycloak.example.com/realms/my-realm", "clientId": "adk-web-ui" } }https://keycloak.example.com/realms/{realm}https://dev-{id}.okta.comhttps://{tenant}.auth0.comhttps://login.microsoftonline.com/{tenant}/v2.0Security model
Design decisions
oidc-client-tsoverkeycloak-js: Provider-agnostic, standard OIDC, smaller surface, no Keycloak-specific config (realm in adapter)APP_INITIALIZERis deprecated in Angular 21;provideHttpClient(withInterceptors([fn]))is the modern patternAuthService.init()deduplicates concurrent calls via stored promiseTest plan
npx ng build) with zero new errors