You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(apisix): send OIDC hosts to a canonical https origin before openid-connect (#5525)
* fix(apisix): send OIDC hosts to a canonical https origin before openid-connect
The shared-plugin defaults already carry APISIX's `redirect` plugin with
http_to_https, but `redirect` has a lower priority than openid-connect (2599),
and APISIX dispatches a phase in descending priority. On every OIDC-protected
route the upgrade therefore never runs: openid-connect has already answered.
That matters because APISIX derives only a relative redirect_uri and
lua-resty-openidc 1.8.0 -- the version APISIX 3.17 pins -- makes it absolute
from ngx.var.scheme and ngx.var.http_host. Both are raw connection values, so
a plain-HTTP request sends Keycloak an http:// redirect_uri and a request
carrying `Host: <host>:443` sends an authority with the port still on it.
Keycloak registers bare-host https URIs only and rejects both with
error="invalid_redirect_uri", killing the login at the authorization endpoint
before any callback exists for the recovery function to rescue. Reproduced
against production on both api.learn and nb.learn, so this is not specific to
the host the Keycloak log happens to show most.
Worse than the failed logins: with the upgrade shadowed, APISIX answers plain
-HTTP requests to these hosts with an OIDC session cookie over cleartext and
without the Secure attribute.
Redirecting is what fixes this rather than setting X-Forwarded-Proto and
X-Forwarded-Host. lua-resty-openidc does prefer those headers over the ngx
vars, but on this deployment none of Forwarded / X-Forwarded-Proto /
X-Forwarded-Host reaches it -- sending each against production leaves the
redirect_uri unchanged -- so pinning them would be a no-op that reads like a
fix.
APISIX keys a plugin config by plugin name, so a route can carry exactly one
serverless-pre-function, and both this and the error-callback recovery have to
run ahead of openid-connect. They are consequently one plugin with two
functions rather than two plugins, which is why the builder is renamed.
serverless/init.lua runs `functions` in array order and stops at the first
returning a code, so the origin is normalised before recovery decides whether
to redirect back into a login flow -- otherwise recovery would target an
http:// origin and fail again.
Leaving port 80 answering with a redirect is only safe because every ACME
ClusterIssuer on the cluster solves via dns01/Route53; an issuer switched to
http-01 would need its challenge path carved out.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G9yBC9UqoVwiPtxqLNgUD9
* fix(apisix): validate the redirect status, correct the 308 rationale
Copilot review on #5525, both points verified against source before acting.
ngx.redirect accepts only 301/302/303/307/308 and raises a Lua error on
anything else (ngx_http_lua_control.c:209-219). The block this setting travels
in is not part of serverless-pre-function's schema, so APISIX will not reject a
bad value either -- it would first surface as a 500 on live traffic. The
`Literal` annotation alone does not prevent that: this repo's mypy hook runs
without the project installed, so a cross-module call resolves to Any and the
bad literal passes. Validating in the builder moves the failure to `pulumi
preview`, with tests over both the accepted and rejected sets.
The 308 rationale was also wrong. APISIX's `redirect` plugin is method-dependent
-- 301 for GET/HEAD, 308 for everything else (redirect.lua:208-215) -- so it
would not have downgraded a POST, and the previous comment claimed a
behavioural fix where there is only a simplification to one uniform status.
Corrected in the Lua comment and the docstring.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G9yBC9UqoVwiPtxqLNgUD9
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
0 commit comments