outposts/proxy: fix potential empty redirect, add tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> #2141
This commit is contained in:
		@ -71,7 +71,7 @@ func TestForwardHandleNginx_Single_Claims(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rr = httptest.NewRecorder()
 | 
			
		||||
	a.forwardHandleTraefik(rr, req)
 | 
			
		||||
	a.forwardHandleNginx(rr, req)
 | 
			
		||||
 | 
			
		||||
	h := rr.Result().Header
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -79,5 +79,6 @@ func (a *Application) proxyModifyRequest(u *url.URL) func(req *http.Request) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *Application) proxyModifyResponse(res *http.Response) error {
 | 
			
		||||
	res.Header.Set("X-Powered-By", "authentik_proxy2")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -26,21 +26,14 @@ func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		a.log.WithError(err).Warning("failed to decode session")
 | 
			
		||||
	}
 | 
			
		||||
	redirectUrl := r.URL.String()
 | 
			
		||||
	// simple way to copy the URL
 | 
			
		||||
	u, _ := url.Parse(redirectUrl)
 | 
			
		||||
	// In proxy and forward_single mode we only have one URL that we route on
 | 
			
		||||
	// if we somehow got here without that URL, make sure we're at least redirected back to it
 | 
			
		||||
	if a.Mode() == api.PROXYMODE_PROXY || a.Mode() == api.PROXYMODE_FORWARD_SINGLE {
 | 
			
		||||
		u.Host = a.proxyConfig.ExternalHost
 | 
			
		||||
	}
 | 
			
		||||
	redirectUrl := urlJoin(a.proxyConfig.ExternalHost, r.URL.Path)
 | 
			
		||||
	if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN {
 | 
			
		||||
		dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".")
 | 
			
		||||
		// In forward_domain we only check that the current URL's host
 | 
			
		||||
		// ends with the cookie domain (remove the leading period if set)
 | 
			
		||||
		if !strings.HasSuffix(r.URL.Hostname(), dom) {
 | 
			
		||||
			a.log.WithField("url", r.URL.String()).WithField("cd", dom).Warning("Invalid redirect found")
 | 
			
		||||
			redirectUrl = ""
 | 
			
		||||
			redirectUrl = a.proxyConfig.ExternalHost
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	s.Values[constants.SessionRedirect] = redirectUrl
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										81
									
								
								internal/outpost/proxyv2/application/utils_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								internal/outpost/proxyv2/application/utils_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
			
		||||
package application
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"goauthentik.io/api"
 | 
			
		||||
	"goauthentik.io/internal/outpost/proxyv2/constants"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestRedirectToStart_Proxy(t *testing.T) {
 | 
			
		||||
	a := newTestApplication()
 | 
			
		||||
	a.proxyConfig.Mode = api.PROXYMODE_PROXY.Ptr()
 | 
			
		||||
	a.proxyConfig.ExternalHost = "https://test.goauthentik.io"
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil)
 | 
			
		||||
 | 
			
		||||
	rr := httptest.NewRecorder()
 | 
			
		||||
	a.redirectToStart(rr, req)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, http.StatusFound, rr.Code)
 | 
			
		||||
	loc, _ := rr.Result().Location()
 | 
			
		||||
	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String())
 | 
			
		||||
 | 
			
		||||
	s, _ := a.sessions.Get(req, constants.SeesionName)
 | 
			
		||||
	assert.Equal(t, "https://test.goauthentik.io/foo/bar/baz", s.Values[constants.SessionRedirect])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRedirectToStart_Forward(t *testing.T) {
 | 
			
		||||
	a := newTestApplication()
 | 
			
		||||
	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_SINGLE.Ptr()
 | 
			
		||||
	a.proxyConfig.ExternalHost = "https://test.goauthentik.io"
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil)
 | 
			
		||||
 | 
			
		||||
	rr := httptest.NewRecorder()
 | 
			
		||||
	a.redirectToStart(rr, req)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, http.StatusFound, rr.Code)
 | 
			
		||||
	loc, _ := rr.Result().Location()
 | 
			
		||||
	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String())
 | 
			
		||||
 | 
			
		||||
	s, _ := a.sessions.Get(req, constants.SeesionName)
 | 
			
		||||
	assert.Equal(t, "https://test.goauthentik.io/foo/bar/baz", s.Values[constants.SessionRedirect])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRedirectToStart_Forward_Domain_Invalid(t *testing.T) {
 | 
			
		||||
	a := newTestApplication()
 | 
			
		||||
	a.proxyConfig.CookieDomain = api.PtrString("foo")
 | 
			
		||||
	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr()
 | 
			
		||||
	a.proxyConfig.ExternalHost = "https://test.goauthentik.io"
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil)
 | 
			
		||||
 | 
			
		||||
	rr := httptest.NewRecorder()
 | 
			
		||||
	a.redirectToStart(rr, req)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, http.StatusFound, rr.Code)
 | 
			
		||||
	loc, _ := rr.Result().Location()
 | 
			
		||||
	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String())
 | 
			
		||||
 | 
			
		||||
	s, _ := a.sessions.Get(req, constants.SeesionName)
 | 
			
		||||
	assert.Equal(t, "https://test.goauthentik.io", s.Values[constants.SessionRedirect])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRedirectToStart_Forward_Domain(t *testing.T) {
 | 
			
		||||
	a := newTestApplication()
 | 
			
		||||
	a.proxyConfig.CookieDomain = api.PtrString("goauthentik.io")
 | 
			
		||||
	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr()
 | 
			
		||||
	a.proxyConfig.ExternalHost = "https://test.goauthentik.io"
 | 
			
		||||
	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil)
 | 
			
		||||
 | 
			
		||||
	rr := httptest.NewRecorder()
 | 
			
		||||
	a.redirectToStart(rr, req)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, http.StatusFound, rr.Code)
 | 
			
		||||
	loc, _ := rr.Result().Location()
 | 
			
		||||
	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String())
 | 
			
		||||
 | 
			
		||||
	s, _ := a.sessions.Get(req, constants.SeesionName)
 | 
			
		||||
	assert.Equal(t, "https://test.goauthentik.io", s.Values[constants.SessionRedirect])
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user