Summary
Add an opt-in, dev-only flag to allow a plain-HTTP, non-localhost upstream OIDC issuer for the embedded auth server's federation, so it can federate to an in-cluster dev IdP (e.g. Dex) served over HTTP in a local Kubernetes environment. Default stays strict (HTTPS).
Problem
The embedded auth server hard-requires HTTPS for a non-localhost upstream issuer, with no override:
validateIssuerURL (pkg/authserver/config.go) → http scheme is only allowed for localhost, use https for %s
validateEndpointOrigin (pkg/authserver/upstream/oidc.go, ~L582–597) → scheme mismatch: ... all endpoints must use HTTPS for non-localhost issuers
The localhost carve-out doesn't help a containerized dev setup: in a kind/k8s cluster the upstream issuer must be a Service-DNS hostname (non-localhost) so that both in-cluster pods (server-side discovery/token exchange) and the host browser (redirect to /authorize) resolve the same issuer URL. localhost only works for the browser, not for the pods — the classic split-horizon.
Two things that look like they'd help but don't:
INSECURE_DISABLE_URL_VALIDATION is honored by networking.ValidatingTransport / ValidateEndpointURL, but not by validateIssuerURL / validateEndpointOrigin — those are a separate validation path.
OIDCUpstreamRunConfig has AllowPrivateIPs (relaxes private-IP destinations) but no field to relax the scheme, and no CACert / InsecureSkipVerify for the discovery/token client — so even a self-signed HTTPS dev IdP can't be trusted without injecting a CA into the AS pod's system trust store.
Net: you cannot federate the embedded AS to an in-cluster HTTP dev IdP at all, and a self-signed HTTPS one needs system-trust-store surgery.
Use case
A local, zero-real-IdP dev environment on kind that federates the embedded auth server to a single in-cluster Dex as the corp IdP. In that setup, other components already tolerate a plain-HTTP in-cluster issuer (e.g. a resource server that only fetches JWKS, or a browser/Node relying party) — only the embedded auth server's upstream federation is blocked by the hard HTTPS requirement.
Proposal
Add an opt-in field to OIDCUpstreamRunConfig (threaded into the upstream provider + authserver.Config), e.g.:
upstreams:
- name: dev-idp
type: oidc
oidc_config:
issuer_url: http://dex.my-ns.svc.cluster.local:5556
insecure_allow_http: true # dev only; default false
insecure_allow_http (default false) relaxes the HTTPS requirement for the upstream issuer and its discovery endpoints (validateIssuerURL + validateEndpointOrigin), scoped per-upstream and threaded from RunConfig (not a global env), clearly named as insecure, never intended for production.
This mirrors the existing localhost dev carve-out and the insecure-http allowances already present on the incoming side; it just extends the same dev ergonomics to the upstream/federation path.
Alternatives considered
- Self-signed HTTPS dev IdP + CA distribution — no values-level
CACert/InsecureSkipVerify on the upstream client, so it requires injecting the CA into the AS pod's system trust store (often a custom image). Heavy and brittle for local dev.
localhost issuer — breaks in-cluster resolution (pods can't reach the browser's localhost).
Notes
- Keep the default strict; this is purely a local-development ergonomics request.
- Observed in
v0.31.0; the validators referenced above are current (latest release v0.34.0).
- Context: surfaced while building a kind-based local dev environment for the Stacklok Enterprise connector-gateway (whose embedded auth server is toolhive's
pkg/authserver).
Summary
Add an opt-in, dev-only flag to allow a plain-HTTP, non-localhost upstream OIDC issuer for the embedded auth server's federation, so it can federate to an in-cluster dev IdP (e.g. Dex) served over HTTP in a local Kubernetes environment. Default stays strict (HTTPS).
Problem
The embedded auth server hard-requires HTTPS for a non-localhost upstream issuer, with no override:
validateIssuerURL(pkg/authserver/config.go) →http scheme is only allowed for localhost, use https for %svalidateEndpointOrigin(pkg/authserver/upstream/oidc.go, ~L582–597) →scheme mismatch: ... all endpoints must use HTTPS for non-localhost issuersThe localhost carve-out doesn't help a containerized dev setup: in a kind/k8s cluster the upstream issuer must be a Service-DNS hostname (non-localhost) so that both in-cluster pods (server-side discovery/token exchange) and the host browser (redirect to
/authorize) resolve the same issuer URL.localhostonly works for the browser, not for the pods — the classic split-horizon.Two things that look like they'd help but don't:
INSECURE_DISABLE_URL_VALIDATIONis honored bynetworking.ValidatingTransport/ValidateEndpointURL, but not byvalidateIssuerURL/validateEndpointOrigin— those are a separate validation path.OIDCUpstreamRunConfighasAllowPrivateIPs(relaxes private-IP destinations) but no field to relax the scheme, and noCACert/InsecureSkipVerifyfor the discovery/token client — so even a self-signed HTTPS dev IdP can't be trusted without injecting a CA into the AS pod's system trust store.Net: you cannot federate the embedded AS to an in-cluster HTTP dev IdP at all, and a self-signed HTTPS one needs system-trust-store surgery.
Use case
A local, zero-real-IdP dev environment on kind that federates the embedded auth server to a single in-cluster Dex as the corp IdP. In that setup, other components already tolerate a plain-HTTP in-cluster issuer (e.g. a resource server that only fetches JWKS, or a browser/Node relying party) — only the embedded auth server's upstream federation is blocked by the hard HTTPS requirement.
Proposal
Add an opt-in field to
OIDCUpstreamRunConfig(threaded into the upstream provider +authserver.Config), e.g.:insecure_allow_http(default false) relaxes the HTTPS requirement for the upstream issuer and its discovery endpoints (validateIssuerURL+validateEndpointOrigin), scoped per-upstream and threaded fromRunConfig(not a global env), clearly named as insecure, never intended for production.This mirrors the existing localhost dev carve-out and the insecure-http allowances already present on the incoming side; it just extends the same dev ergonomics to the upstream/federation path.
Alternatives considered
CACert/InsecureSkipVerifyon the upstream client, so it requires injecting the CA into the AS pod's system trust store (often a custom image). Heavy and brittle for local dev.localhostissuer — breaks in-cluster resolution (pods can't reach the browser'slocalhost).Notes
v0.31.0; the validators referenced above are current (latest releasev0.34.0).pkg/authserver).