Skip to content

Commit

Permalink
fix: gracefully handle double slashes in URLs
Browse files Browse the repository at this point in the history
Closes #779
  • Loading branch information
aeneasr committed Oct 22, 2020
1 parent fea2e77 commit aeb9414
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cmd/daemon/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ func servePublic(d driver.Driver, wg *sync.WaitGroup, cmd *cobra.Command, args [
c.SelfPublicURL().Hostname(),
!flagx.MustGetBool(cmd, "dev"),
)

n.UseFunc(x.CleanPath) // Prevent double slashes from breaking CSRF.
r.WithCSRFHandler(csrf)
n.UseHandler(r.CSRFHandler())

Expand Down
13 changes: 13 additions & 0 deletions internal/testhelpers/httptest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package testhelpers

import (
"net/http"
"net/http/httptest"
"testing"
)

func NewHTTPTestServer(t *testing.T, h http.Handler) *httptest.Server {
ts := httptest.NewServer(h)
t.Cleanup(ts.Close)
return ts
}
2 changes: 2 additions & 0 deletions selfservice/flow/login/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type (
session.ManagementProvider
x.WriterProvider
x.CSRFTokenGeneratorProvider
x.CSRFProvider
}
HandlerProvider interface {
LoginHandler() *Handler
Expand All @@ -48,6 +49,7 @@ func NewHandler(d handlerDependencies, c configuration.Provider) *Handler {
}

func (h *Handler) RegisterPublicRoutes(public *x.RouterPublic) {
h.d.CSRFHandler().ExemptPath(RouteInitAPIFlow)
public.GET(RouteInitBrowserFlow, h.initBrowserFlow)
public.GET(RouteInitAPIFlow, h.initAPIFlow)
public.GET(RouteGetFlow, h.fetchFlow)
Expand Down
3 changes: 3 additions & 0 deletions selfservice/flow/recovery/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type (
FlowPersistenceProvider
x.CSRFTokenGeneratorProvider
x.WriterProvider
x.CSRFProvider
}
Handler struct {
d handlerDependencies
Expand All @@ -48,6 +49,8 @@ func NewHandler(d handlerDependencies, c configuration.Provider) *Handler {
}

func (h *Handler) RegisterPublicRoutes(public *x.RouterPublic) {
h.d.CSRFHandler().ExemptPath(RouteInitAPIFlow)

redirect := session.RedirectOnAuthenticated(h.c)
public.GET(RouteInitBrowserFlow, h.d.SessionHandler().IsNotAuthenticated(h.initBrowserFlow, redirect))
public.GET(RouteInitAPIFlow, h.d.SessionHandler().IsNotAuthenticated(h.initAPIFlow,
Expand Down
3 changes: 3 additions & 0 deletions selfservice/flow/registration/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type (
x.CSRFTokenGeneratorProvider
HookExecutorProvider
FlowPersistenceProvider
x.CSRFProvider
}
HandlerProvider interface {
RegistrationHandler() *Handler
Expand All @@ -48,6 +49,8 @@ func NewHandler(d handlerDependencies, c configuration.Provider) *Handler {
}

func (h *Handler) RegisterPublicRoutes(public *x.RouterPublic) {
h.d.CSRFHandler().ExemptPath(RouteInitAPIFlow)

public.GET(RouteInitBrowserFlow, h.d.SessionHandler().IsNotAuthenticated(h.initBrowserFlow, session.RedirectOnAuthenticated(h.c)))
public.GET(RouteInitAPIFlow, h.d.SessionHandler().IsNotAuthenticated(h.initApiFlow,
session.RespondWithJSONErrorOnAuthenticated(h.d.Writer(), errors.WithStack(ErrAlreadyLoggedIn))))
Expand Down
3 changes: 3 additions & 0 deletions selfservice/flow/settings/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type (
StrategyProvider

IdentityTraitsSchemas() schema.Schemas
x.CSRFProvider
}
HandlerProvider interface {
SettingsHandler() *Handler
Expand All @@ -73,6 +74,8 @@ func NewHandler(d handlerDependencies, c configuration.Provider) *Handler {
}

func (h *Handler) RegisterPublicRoutes(public *x.RouterPublic) {
h.d.CSRFHandler().ExemptPath(RouteInitAPIFlow)

redirect := session.RedirectOnUnauthenticated(h.c.SelfServiceFlowLoginUI().String())
public.GET(RouteInitBrowserFlow, h.d.SessionHandler().IsAuthenticated(h.initBrowserFlow, redirect))
public.GET(RouteInitAPIFlow, h.d.SessionHandler().IsAuthenticated(h.initApiFlow, nil))
Expand Down
3 changes: 3 additions & 0 deletions selfservice/flow/verification/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type (
FlowPersistenceProvider
ErrorHandlerProvider
StrategyProvider
x.CSRFProvider
}
Handler struct {
d handlerDependencies
Expand All @@ -48,6 +49,8 @@ func NewHandler(d handlerDependencies, c configuration.Provider) *Handler {
}

func (h *Handler) RegisterPublicRoutes(public *x.RouterPublic) {
h.d.CSRFHandler().ExemptPath(RouteInitAPIFlow)

public.GET(RouteInitBrowserFlow, h.initBrowserFlow)
public.GET(RouteInitAPIFlow, h.initAPIFlow)
public.GET(RouteGetFlow, h.fetch)
Expand Down
13 changes: 13 additions & 0 deletions x/clean_url.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package x

import (
"net/http"

"github.com/julienschmidt/httprouter"
"github.com/urfave/negroni"
)

var CleanPath negroni.HandlerFunc = func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
r.URL.Path = httprouter.CleanPath(r.URL.Path)
next(rw, r)
}
35 changes: 35 additions & 0 deletions x/clean_url_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package x

import (
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"

"github.com/bmizerany/assert"
"github.com/stretchr/testify/require"
"github.com/urfave/negroni"
)

func TestCleanPath(t *testing.T) {
n := negroni.New(CleanPath)
n.UseHandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(r.URL.String()))
})
ts := httptest.NewServer(n)
defer ts.Close()

for k, tc := range [][]string{
{"//foo", "/foo"},
{"//foo//bar", "/foo/bar"},
} {
t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) {
res, err := ts.Client().Get(ts.URL + tc[0])
require.NoError(t, err)
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
assert.Equal(t, string(body), tc[1])
})
}
}

0 comments on commit aeb9414

Please sign in to comment.