diff --git a/internal/outpost/proxyv2/application/oauth.go b/internal/outpost/proxyv2/application/oauth.go index 172b98b629..7b8df2f505 100644 --- a/internal/outpost/proxyv2/application/oauth.go +++ b/internal/outpost/proxyv2/application/oauth.go @@ -76,7 +76,7 @@ func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) { } } - redirectUrl := urlJoin(a.proxyConfig.ExternalHost, r.URL.Path) + redirectUrl := urlJoin(a.proxyConfig.ExternalHost, r.URL.EscapedPath()) if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN { dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".") diff --git a/internal/outpost/proxyv2/application/utils_test.go b/internal/outpost/proxyv2/application/utils_test.go index eb6f34935d..1f942f2bda 100644 --- a/internal/outpost/proxyv2/application/utils_test.go +++ b/internal/outpost/proxyv2/application/utils_test.go @@ -27,6 +27,24 @@ func TestRedirectToStart_Proxy(t *testing.T) { assert.Equal(t, "https://test.goauthentik.io/foo/bar/baz", s.Values[constants.SessionRedirect]) } +func TestRedirectToStart_Proxy_EncodedSlash(t *testing.T) { + a := newTestApplication() + a.proxyConfig.Mode = api.PROXYMODE_PROXY.Ptr() + a.proxyConfig.ExternalHost = "https://test.goauthentik.io" + // %2F is a URL-encoded forward slash, used by apps like RabbitMQ in queue paths + req, _ := http.NewRequest("GET", "/api/queues/%2F/MYChannelCreated", nil) + + rr := httptest.NewRecorder() + a.redirectToStart(rr, req) + + assert.Equal(t, http.StatusFound, rr.Code) + loc, _ := rr.Result().Location() + assert.Contains(t, loc.String(), "%252F", "encoded slash %2F must be preserved in redirect URL") + + s, _ := a.sessions.Get(req, a.SessionName()) + assert.Contains(t, s.Values[constants.SessionRedirect].(string), "%2F", "encoded slash %2F must be preserved in session redirect") +} + func TestRedirectToStart_Forward(t *testing.T) { a := newTestApplication() a.proxyConfig.Mode = api.PROXYMODE_FORWARD_SINGLE.Ptr()