fix: serve the OAuth discovery document without authentication - #1095
fix: serve the OAuth discovery document without authentication#1095thomasvvugt wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the web server router to serve the OpenShift OAuth discovery document (/.well-known/oauth-authorization-server) without requiring prior authentication, enabling oc login <proxy-host> --web and other OAuth authorization-code clients to complete their initial discovery step successfully through the proxy.
Changes:
- Registers
/.well-known/oauth-authorization-serveron the top-level router (outside the authenticated subrouter). - Forwards that endpoint directly to the upstream API server via the existing reverse proxy.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
a2ea64f to
4f536ef
Compare
Clients that use the OAuth authorization code flow, such as 'oc login <host> --web', retrieve /.well-known/oauth-authorization-server from the API endpoint before any credentials exist. The proxy rejected these requests because user resolution requires authentication, so the login aborted before the browser flow could start. The upstream API server already answers this path anonymously, so register it on the top-level router, like /_healthz, and hand it to the reverse proxy. Signed-off-by: Thomas van Vugt <thomas.vugt@rvig.nl>
4f536ef to
b86e6f3
Compare
|
We should implement this more generic, instead of having that single path we should add a slice var as argument where paths can be provided, which are passed. We already have |
|
Hi, makes sense. Happy to rework this PR onto a flag (e.g. --unauthenticated-paths or extending allowedPaths with a separate unauthenticated set), or leave it to you. I can validate against our cluster. |
|
You will need the following args: @thomasvvugt Can you verify with changes in #1096 |
|
Verified #1096 against our cluster; the binding fix works, but anonymous requests still get rejected before the allowed-paths check. It looks like the auth-type loop in internal/request/http.go skips Anonymous explicitly ("capsule-proxy does not support unauthenticated users"), and that happens upstream of CheckPaths. Adding When we are using |
|
@thomasvvugt Forgot about the authentication, but another bug fixed. Can you try this, is now a dedicated flag: |
|
@thomasvvugt will be released today, do you think we should expand the oc docs with this case? |
|
Hi @oliverbaehler , yes please, a short section on that page would help. The pieces that mattered for us:
Happy to write the section as a PR against the docs, we validated the full flow against a HyperShift (HostedControlPlane) cluster with exactly that flag. |
|
@thomasvvugt if you have time contributing to the docs that would be great |
|
Picked up the docs suggestion: projectcapsule/website#131 adds a hosted-control-planes section for the oc login --web flow. Thanks for the quick help on this! |
oc login <proxy-host> --web(and any client using the OAuth authorization code flow) requests/.well-known/oauth-authorization-serverfrom the API endpoint before it has any credentials. The proxy requires authentication to resolve the user on every request, so this request was rejected and the login aborted before the browser flow could even start (oc then fails with a confusingunsupported protocol scheme "").The upstream API server already serves this document for anonymous requests, so the proxy can simply forward it. This registers the path on the top-level router next to
/_healthz, outside the authenticated subrouter, and hands it to the reverse proxy.Validated against an OpenShift cluster (Hypershift-hosted control plane, Kubernetes 1.33):
GET /.well-known/oauth-authorization-serverwithout credentials:200with the cluster OAuth metadata, identical to the API server responseGET /versionandGET /api/v1/namespaceswithout credentials: still403, the authentication requirement is unchanged for everything elseWith this in place
oc login <proxy-host> --webcompletes against capsule-proxy on OpenShift: discovery succeeds, the browser flow runs against the cluster OAuth server, and the token exchange and API traffic go through the proxy as usual.Unrelated but worth flagging while testing:
maincurrently panics on startup when no bearer token is configured (bearerExpirationTimedereferences the nil token returned by the jwt v5ParseUnverifiedon empty input,webserver.go:826-827). I carried a local nil guard to run the validation above; happy to send that as a separate PR if useful.