github.com/greenpau/go-authcrunch@v1.1.4/pkg/authn/respond_http_test.go (about) 1 // Copyright 2022 Paul Greenberg greenpau@outlook.com 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package authn 16 17 import ( 18 "context" 19 "github.com/greenpau/go-authcrunch/internal/tests" 20 "github.com/greenpau/go-authcrunch/pkg/authn/cookie" 21 "github.com/greenpau/go-authcrunch/pkg/authn/ui" 22 "github.com/greenpau/go-authcrunch/pkg/requests" 23 "go.uber.org/zap" 24 "net/http" 25 "net/url" 26 "strings" 27 "testing" 28 ) 29 30 type customResponseWriter struct { 31 body []byte 32 statusCode int 33 header http.Header 34 } 35 36 func buildCustomResponseWriter() *customResponseWriter { 37 return &customResponseWriter{ 38 header: http.Header{}, 39 } 40 } 41 42 func (w *customResponseWriter) Header() http.Header { 43 return w.header 44 } 45 46 func (w *customResponseWriter) Write(b []byte) (int, error) { 47 w.body = b 48 return 0, nil 49 } 50 51 func (w *customResponseWriter) WriteHeader(statusCode int) { 52 w.statusCode = statusCode 53 } 54 55 func TestInjectRedirectURL(t *testing.T) { 56 57 t.Run("Strips login hint from redirect URL if present", func(t *testing.T) { 58 reqURL := url.URL{ 59 Scheme: "https", 60 Host: "foo.bar", 61 Path: "/myPage", 62 RawQuery: "redirect_url=https%3A%2F%2Ffoo.bar%2Fredir%3Flogin_hint%3Dmy%40email.com", 63 } 64 r := http.Request{URL: &reqURL, Method: "GET"} 65 f, _ := cookie.NewFactory(nil) 66 p := Portal{ 67 config: &PortalConfig{ 68 Name: "somePortal", 69 }, 70 logger: zap.L(), 71 cookie: f, 72 } 73 request := requests.NewRequest() 74 75 p.injectRedirectURL(context.Background(), buildCustomResponseWriter(), &r, request) 76 77 cookieParts := strings.Split(request.Response.RedirectURL, ";") 78 tests.EvalObjectsWithLog(t, "redirect url", "AUTHP_REDIRECT_URL=https://foo.bar/redir", cookieParts[0], []string{}) 79 }) 80 } 81 82 func TestRefererSanitization(t *testing.T) { 83 t.Run("should sanitize referral url if its malformed in a way that is intended to cause a XSS", func(t *testing.T) { 84 reqURL := url.URL{ 85 Scheme: "https", 86 Host: "foo.bar", 87 Path: "/myPage", 88 RawQuery: "redirect_url=https%3A%2F%2Ffoo.bar%2Fredir", 89 } 90 r := http.Request{URL: &reqURL, Method: "GET"} 91 r.Header = make(http.Header) 92 maliciousURL := "https://www.google.com/search?hl=en&q=testing'\"()&%<acx><ScRiPt >alert(9854)</ScRiPt>" 93 r.Header.Set("Referer", maliciousURL) 94 f, _ := cookie.NewFactory(nil) 95 uiFactory := ui.NewFactory() 96 p := Portal{ 97 config: &PortalConfig{ 98 Name: "somePortal", 99 UI: &ui.Parameters{ 100 Theme: "", 101 }, 102 }, 103 logger: zap.L(), 104 cookie: f, 105 ui: uiFactory, 106 } 107 _ = p.configureUserInterface() 108 request := requests.NewRequest() 109 rw := buildCustomResponseWriter() 110 111 _ = p.handleHTTPError(context.Background(), rw, &r, request, 404) 112 rb := string(rw.body) 113 114 tests.EvalObjectsWithLog(t, "sanitized url", true, strings.Contains(rb, "https://www.google.com/search?hl=en%26q=testing%27%22()%26%%3Cacx%3E%3CScRiPt %3Ealert(9854)%3C/ScRiPt%3E"), []string{}) 115 }) 116 }