Summary
When a resource protected by forward-auth is requested with a query string (e.g. GET /search?q=hello) while the user is unauthenticated, the redirect_uri tinyauth builds for the login page silently drops the query string. After a successful login the user lands on /search instead of /search?q=hello.
This breaks anything that relies on GET query parameters behind tinyauth — most notably self-hosted search engines (e.g. Degoog, a self-hosted metasearch engine), where the very first unauthenticated search always comes back empty.
Root cause
In internal/controller/proxy_controller.go, getProxyContext explicitly strips the query string when parsing the forwarded request path:
// remove any query params from the request path
upath, err := url.Parse(ctx.Path)
...
ctx.Path = path.Clean(upath.Path)
proxyHandler then builds the login redirect purely from that already-stripped path:
RedirectURI: fmt.Sprintf("%s://%s%s", proxyCtx.Proto, proxyCtx.Host, proxyCtx.Path),
proxyCtx.Path never contains a query string by the time RedirectURI is built, regardless of proxy type (Caddy/Traefik/Nginx/Envoy), since the stripping happens in the shared getProxyContext path before any proxy-specific branching.
Confirmed present on main as of 2026-08, not just an old release.
Reproduction
- Put a search engine (e.g. Degoog, a self-hosted metasearch engine) behind Caddy
forward_auth → tinyauth (uri /api/auth/caddy).
- While logged out, request
https://search.example.com/search?q=hello.
- Get redirected to tinyauth's login page. Inspect the URL:
redirect_uri=https%3A%2F%2Fsearch.example.com%2Fsearch — no q param.
- Log in.
- Land on
https://search.example.com/search with an empty query instead of results for "hello".
Expected behavior
redirect_uri should preserve the full original request (path + query string), so the user lands back exactly where they started after logging in.
Note
This was found with AI assistance (Claude) while debugging the symptom above, and I traced it down to the code quoted here myself. I'm not a Go developer and don't know this codebase's history, so I can't tell whether getProxyContext stripping the query string is a deliberate defensive measure (e.g. against some kind of injection via the redirect target) or just an oversight. Flagging that explicitly in case it's the former — apologies if this turns out to be working as intended, and thanks for taking a look either way.
Summary
When a resource protected by forward-auth is requested with a query string (e.g.
GET /search?q=hello) while the user is unauthenticated, theredirect_uritinyauth builds for the login page silently drops the query string. After a successful login the user lands on/searchinstead of/search?q=hello.This breaks anything that relies on GET query parameters behind tinyauth — most notably self-hosted search engines (e.g. Degoog, a self-hosted metasearch engine), where the very first unauthenticated search always comes back empty.
Root cause
In
internal/controller/proxy_controller.go,getProxyContextexplicitly strips the query string when parsing the forwarded request path:proxyHandlerthen builds the login redirect purely from that already-stripped path:proxyCtx.Pathnever contains a query string by the timeRedirectURIis built, regardless of proxy type (Caddy/Traefik/Nginx/Envoy), since the stripping happens in the sharedgetProxyContextpath before any proxy-specific branching.Confirmed present on
mainas of 2026-08, not just an old release.Reproduction
forward_auth→ tinyauth (uri /api/auth/caddy).https://search.example.com/search?q=hello.redirect_uri=https%3A%2F%2Fsearch.example.com%2Fsearch— noqparam.https://search.example.com/searchwith an empty query instead of results for "hello".Expected behavior
redirect_urishould preserve the full original request (path + query string), so the user lands back exactly where they started after logging in.Note
This was found with AI assistance (Claude) while debugging the symptom above, and I traced it down to the code quoted here myself. I'm not a Go developer and don't know this codebase's history, so I can't tell whether
getProxyContextstripping the query string is a deliberate defensive measure (e.g. against some kind of injection via the redirect target) or just an oversight. Flagging that explicitly in case it's the former — apologies if this turns out to be working as intended, and thanks for taking a look either way.