Summary
In a local Helm install of oci://ghcr.io/i-am-bee/agentstack/chart/agentstack:0.7.1 with the bundled Keycloak and auth.enabled: true, the UI's NextAuth (Auth.js v5 / oauth4webapi) refuses to perform OIDC discovery against the in-cluster Keycloak URL because the URL is plain HTTP. NextAuth falls back to a degraded code path, the resulting access tokens fail audience validation on the backend, and every authenticated UI request returns 401. The user sees "Authentication Error / Server authentication failed" on the signin page and cannot log in. The CLI flow (agentstack server login) is unaffected.
The chart already has AUTH__OIDC__INSECURE_TRANSPORT=true on the agentstack-server deployment for this exact purpose. The agentstack-ui deployment has no equivalent flag, and there is no chart value to enable insecure transport for the UI.
Environment
- Chart:
oci://ghcr.io/i-am-bee/agentstack/chart/agentstack version 0.7.1
- Kubernetes: k3s
v1.34.6+k3s1 (single node, native Linux, no VM)
- Helm:
v3.18.4
- Linux host (Ubuntu/Debian)
- Access pattern:
kubectl port-forward (no Ingress, no TLS), the documented local path
svc/agentstack-ui-svc 8334:8334
svc/agentstack-server-svc 8333:8333
svc/keycloak 8336:8336
Minimal config.yaml
externalRegistries:
public_github: "https://github.com/i-am-bee/agentstack@v0.7.1#path=agent-registry.yaml"
providers:
- location: ghcr.io/i-am-bee/agentstack/agents/chat:0.7.1
encryptionKey: "<fernet>"
auth:
enabled: true
basic:
enabled: true
adminPassword: "..." # ignored by 0.7.x (separate issue)
helm upgrade --install agentstack -f config.yaml oci://ghcr.io/i-am-bee/agentstack/chart/agentstack --version 0.7.1 succeeds. All pods reach Running 1/1. The keycloak-provision job completes successfully.
Reproduction
- Create the user manually in the
agentstack realm via kcadm.sh (or the Keycloak admin UI), with emailVerified=true and the agentstack-admin realm role assigned. (The chart provides no out-of-the-box first-user seeding for a local install.)
- Open
http://localhost:8334 in a browser (private window to rule out cookies).
- Sign in via the Keycloak page with the user above.
- Browser is redirected back to
http://localhost:8334/signin?callbackUrl=%2F showing "Server authentication failed".
What the logs show
agentstack-ui pod
OIDC discovery failed for http://keycloak:8336/realms/agentstack, using fallback: l: only requests to HTTPS are allowed
at m (.next/server/chunks/4647.js:404:135201)
...
at async p (.next/server/app/api/auth/[...nextauth]/route.js:1:8150)
at async q (.next/server/app/api/auth/[...nextauth]/route.js:1:8916)
at async Object.jwt (.next/server/app/api/auth/[...nextauth]/route.js:1:11502)
{
code: 'OAUTH_HTTP_REQUEST_FORBIDDEN',
[cause]: v: only requests to HTTPS are allowed
...
[cause]: URL {
href: 'http://keycloak:8336/realms/agentstack',
protocol: 'http:',
hostname: 'keycloak',
port: '8336',
pathname: '/realms/agentstack',
}
}
agentstack-server pod
warning Token validation failed: invalid_claim: Invalid claim 'aud' [agentstack_server.api.dependencies]
error Error during HTTP request: [('HTTPException', '401: Token validation failed')]
info 10.42.0.24:51730 - "GET /api/v1/providers HTTP/1.1" 401
The aud failure is a downstream symptom of the discovery fallback, not the root cause — see analysis below.
Root cause
NextAuth v5 / Auth.js uses oauth4webapi for OIDC. oauth4webapi rejects any HTTP URL for processDiscoveryResponse / token endpoint requests unless the hostname is exactly localhost, 127.0.0.1, or [::1]. Hostnames like keycloak (the in-cluster K8s service DNS name) are blocked, even though the request is purely intra-cluster.
The chart's agentstack-ui deployment template (helm/templates/ui/deployment.yaml at v0.7.1) sets:
- name: OIDC_PROVIDER_ISSUER
value: {{ include "agentstack.oidc.internalIssuerUrl" . | quote }} # http://keycloak:8336/realms/agentstack
- name: OIDC_PROVIDER_EXTERNAL_ISSUER
value: {{ include "agentstack.oidc.publicIssuerUrl" . | quote }} # http://localhost:8336/realms/agentstack
There is no OIDC_INSECURE_TRANSPORT / AUTH_TRUST_HOST_HTTP / equivalent on the UI container. By contrast, the server template sets:
- name: AUTH__OIDC__INSECURE_TRANSPORT
value: {{ hasPrefix "http://" (include "agentstack.oidc.internalIssuerUrl" . | default "") | quote }}
so the backend correctly opts in to HTTP. The UI cannot.
The fallback path NextAuth takes when discovery fails issues tokens that don't carry the agentstack-server-audience scope, which is why the backend then rejects them with Invalid claim 'aud'. Fixing the audience without fixing discovery does not help (verified by manually attaching agentstack-server-audience as a default scope to the agentstack-ui Keycloak client — server still 401s because the token NextAuth ends up forwarding is from the fallback path).
Verification that the rest of the stack is correct
Issuing a token directly via the Keycloak ROPC grant on the agentstack-ui client (with the audience scope manually attached) and calling the API works end-to-end:
TOKEN=$(curl -s -X POST http://localhost:8336/realms/agentstack/protocol/openid-connect/token \
-d grant_type=password -d client_id=agentstack-ui -d client_secret=$UI_SECRET \
-d username=hunzai -d password=*** -d scope=openid \
| jq -r .access_token)
curl -i -H "Authorization: Bearer $TOKEN" http://localhost:8333/api/v1/providers
# HTTP/1.1 200 OK
# {"items":[{"source":"ghcr.io/i-am-bee/agentstack/agents/rag:0.7.1",...}]}
So Keycloak, the realm, the user, the audience mappers, and the server's token validation all work. The failure is purely in the UI's NextAuth → Keycloak discovery step.
Impact
A first-time user following the deployment guide for a local Helm install on Linux with port-forwarding (no Ingress, no TLS) cannot access the Web UI at all with auth enabled. Combined with the related issue that basic auth is stale and ignored, the only working configuration for this very common scenario is auth.enabled: false.
Proposed fix
Add an opt-in chart value, e.g.:
auth:
uiInsecureTransport: false # default
When set to true, the chart should:
- Set an env var on the
agentstack-ui container that tells Auth.js / oauth4webapi to allow HTTP. There are a few possible mechanisms:
- Pass
OIDC_PROVIDER_ISSUER=http://localhost:8336/... on the UI container together with a hostAliases entry mapping localhost is not possible — but wiring NextAuth's underlying client through [customFetch] with [allowInsecureRequests] is. The UI app would need a small code change to plumb the flag through.
- Or set
process.env.AUTH_TRUST_HOST=true and call oauth4webapi with the [allowInsecureRequests] symbol on the issuer config when an env flag is present.
- Auto-enable when
keycloak.publicIssuerUrl and auth.nextauthUrl both start with http:// (mirrors how AUTH__OIDC__INSECURE_TRANSPORT is auto-derived for the server).
- Default to
false (HTTPS-only) so production installs are unaffected.
Alternatively, document clearly in the deployment guide that auth must be disabled for any HTTP-only local install with chart 0.7.x — currently the docs imply OIDC works locally out of the box, which it does not.
Workaround for affected users
Set auth.enabled: false in values.yaml and helm upgrade. This is the only working configuration for a local HTTP install. The CLI auth path (agentstack server login) is unaffected and continues to work even with OIDC enabled (because the CLI uses a public client and a real browser, not Auth.js server-side).
Related
- Existing issue noting that the deployment guide's basic auth section is stale and that auth is now binary (disabled vs OIDC). The current report is the OIDC half of that picture: OIDC also doesn't work in the most common local setup.
Summary
In a local Helm install of
oci://ghcr.io/i-am-bee/agentstack/chart/agentstack:0.7.1with the bundled Keycloak andauth.enabled: true, the UI's NextAuth (Auth.js v5 /oauth4webapi) refuses to perform OIDC discovery against the in-cluster Keycloak URL because the URL is plain HTTP. NextAuth falls back to a degraded code path, the resulting access tokens fail audience validation on the backend, and every authenticated UI request returns 401. The user sees "Authentication Error / Server authentication failed" on the signin page and cannot log in. The CLI flow (agentstack server login) is unaffected.The chart already has
AUTH__OIDC__INSECURE_TRANSPORT=trueon theagentstack-serverdeployment for this exact purpose. Theagentstack-uideployment has no equivalent flag, and there is no chart value to enable insecure transport for the UI.Environment
oci://ghcr.io/i-am-bee/agentstack/chart/agentstackversion0.7.1v1.34.6+k3s1(single node, native Linux, no VM)v3.18.4kubectl port-forward(no Ingress, no TLS), the documented local pathsvc/agentstack-ui-svc 8334:8334svc/agentstack-server-svc 8333:8333svc/keycloak 8336:8336Minimal
config.yamlhelm upgrade --install agentstack -f config.yaml oci://ghcr.io/i-am-bee/agentstack/chart/agentstack --version 0.7.1succeeds. All pods reachRunning 1/1. Thekeycloak-provisionjob completes successfully.Reproduction
agentstackrealm viakcadm.sh(or the Keycloak admin UI), withemailVerified=trueand theagentstack-adminrealm role assigned. (The chart provides no out-of-the-box first-user seeding for a local install.)http://localhost:8334in a browser (private window to rule out cookies).http://localhost:8334/signin?callbackUrl=%2Fshowing "Server authentication failed".What the logs show
agentstack-uipodagentstack-serverpodThe
audfailure is a downstream symptom of the discovery fallback, not the root cause — see analysis below.Root cause
NextAuth v5 / Auth.js uses
oauth4webapifor OIDC.oauth4webapirejects any HTTP URL forprocessDiscoveryResponse/ token endpoint requests unless the hostname is exactlylocalhost,127.0.0.1, or[::1]. Hostnames likekeycloak(the in-cluster K8s service DNS name) are blocked, even though the request is purely intra-cluster.The chart's
agentstack-uideployment template (helm/templates/ui/deployment.yamlat v0.7.1) sets:There is no
OIDC_INSECURE_TRANSPORT/AUTH_TRUST_HOST_HTTP/ equivalent on the UI container. By contrast, the server template sets:so the backend correctly opts in to HTTP. The UI cannot.
The fallback path NextAuth takes when discovery fails issues tokens that don't carry the
agentstack-server-audiencescope, which is why the backend then rejects them withInvalid claim 'aud'. Fixing the audience without fixing discovery does not help (verified by manually attachingagentstack-server-audienceas a default scope to theagentstack-uiKeycloak client — server still 401s because the token NextAuth ends up forwarding is from the fallback path).Verification that the rest of the stack is correct
Issuing a token directly via the Keycloak ROPC grant on the
agentstack-uiclient (with the audience scope manually attached) and calling the API works end-to-end:So Keycloak, the realm, the user, the audience mappers, and the server's token validation all work. The failure is purely in the UI's NextAuth → Keycloak discovery step.
Impact
A first-time user following the deployment guide for a local Helm install on Linux with port-forwarding (no Ingress, no TLS) cannot access the Web UI at all with auth enabled. Combined with the related issue that basic auth is stale and ignored, the only working configuration for this very common scenario is
auth.enabled: false.Proposed fix
Add an opt-in chart value, e.g.:
When set to
true, the chart should:agentstack-uicontainer that tells Auth.js /oauth4webapito allow HTTP. There are a few possible mechanisms:OIDC_PROVIDER_ISSUER=http://localhost:8336/...on the UI container together with ahostAliasesentry mappinglocalhostis not possible — but wiring NextAuth's underlying client through[customFetch]with[allowInsecureRequests]is. The UI app would need a small code change to plumb the flag through.process.env.AUTH_TRUST_HOST=trueand calloauth4webapiwith the[allowInsecureRequests]symbol on the issuer config when an env flag is present.keycloak.publicIssuerUrlandauth.nextauthUrlboth start withhttp://(mirrors howAUTH__OIDC__INSECURE_TRANSPORTis auto-derived for the server).false(HTTPS-only) so production installs are unaffected.Alternatively, document clearly in the deployment guide that auth must be disabled for any HTTP-only local install with chart 0.7.x — currently the docs imply OIDC works locally out of the box, which it does not.
Workaround for affected users
Set
auth.enabled: falseinvalues.yamlandhelm upgrade. This is the only working configuration for a local HTTP install. The CLI auth path (agentstack server login) is unaffected and continues to work even with OIDC enabled (because the CLI uses a public client and a real browser, not Auth.js server-side).Related