@@ -54,7 +54,7 @@ func TestRobotsTxt(t *testing.T) {
5454 t.Fatal(err)
5555 }
5656 rw := httptest.NewRecorder()
57− req, _ := http.NewRequest("GET", "/robots.txt", nil)
57+ req, _ := http.NewRequest(http.MethodGet, "/robots.txt", nil)
5858 proxy.ServeHTTP(rw, req)
5959 assert.Equal(t, 200, rw.Code)
6060 assert.Equal(t, "User-agent: *\nDisallow: /\n", rw.Body.String())
@@ -241,7 +241,7 @@ func TestBasicAuthPassword(t *testing.T) {
241241
242242 // Save the required session
243243 rw := httptest.NewRecorder()
244− req, _ := http.NewRequest("GET", "/", nil)
244+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
245245 err = proxy.sessionStore.Save(rw, req, &sessions.SessionState{
246246 Email: emailAddress,
247247 })
@@ -250,7 +250,7 @@ func TestBasicAuthPassword(t *testing.T) {
250250 // Extract the cookie value to inject into the test request
251251 cookie := rw.Header().Values("Set-Cookie")[0]
252252
253− req, _ = http.NewRequest("GET", "/", nil)
253+ req, _ = http.NewRequest(http.MethodGet, "/", nil)
254254 req.Header.Set("Cookie", cookie)
255255 rw = httptest.NewRecorder()
256256 proxy.ServeHTTP(rw, req)
@@ -300,14 +300,14 @@ func TestPassGroupsHeadersWithGroups(t *testing.T) {
300300
301301 // Save the required session
302302 rw := httptest.NewRecorder()
303− req, _ := http.NewRequest("GET", "/", nil)
303+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
304304 err = proxy.sessionStore.Save(rw, req, session)
305305 assert.NoError(t, err)
306306
307307 // Extract the cookie value to inject into the test request
308308 cookie := rw.Header().Values("Set-Cookie")[0]
309309
310− req, _ = http.NewRequest("GET", "/", nil)
310+ req, _ = http.NewRequest(http.MethodGet, "/", nil)
311311 req.Header.Set("Cookie", cookie)
312312 rw = httptest.NewRecorder()
313313 proxy.ServeHTTP(rw, req)
@@ -457,7 +457,7 @@ func (patTest *PassAccessTokenTest) getEndpointWithCookie(cookie string, endpoin
457457 return 0, ""
458458 }
459459
460− req, err := http.NewRequest("GET", endpoint, strings.NewReader(""))
460+ req, err := http.NewRequest(http.MethodGet, endpoint, strings.NewReader(""))
461461 if err != nil {
462462 return 0, ""
463463 }
@@ -608,7 +608,7 @@ func NewSignInPageTest(skipProvider bool) (*SignInPageTest, error) {
608608
609609func (sipTest *SignInPageTest) GetEndpoint(endpoint string) (int, string) {
610610 rw := httptest.NewRecorder()
611− req, _ := http.NewRequest("GET", endpoint, strings.NewReader(""))
611+ req, _ := http.NewRequest(http.MethodGet, endpoint, strings.NewReader(""))
612612 sipTest.proxy.ServeHTTP(rw, req)
613613 return rw.Code, rw.Body.String()
614614}
@@ -713,6 +713,50 @@ func TestManualSignInCorrectCredentials(t *testing.T) {
713713 assert.Equal(t, http.StatusFound, statusCode)
714714}
715715
716+func TestSignInPageClearsExistingSessionCookie(t *testing.T) {
717+ opts := baseTestOptions()
718+ err := validation.Validate(opts)
719+ require.NoError(t, err)
720+
721+ proxy, err := NewOAuthProxy(opts, func(string) bool {
722+ return true
723+ })
724+ require.NoError(t, err)
725+
726+ // Create a real session cookie using the actual session store.
727+ saveRW := httptest.NewRecorder()
728+ saveReq := httptest.NewRequest(http.MethodGet, "/", nil)
729+ err = proxy.sessionStore.Save(saveRW, saveReq, &sessions.SessionState{
730+ Email: "john.doe@example.com",
731+ })
732+ require.NoError(t, err)
733+
734+ cookies := saveRW.Result().Cookies()
735+ require.NotEmpty(t, cookies)
736+
737+ // Send that cookie to the sign-in page.
738+ req := httptest.NewRequest(http.MethodGet, "/oauth2/sign_in", nil)
739+ for _, c := range cookies {
740+ req.AddCookie(c)
741+ }
742+
743+ rw := httptest.NewRecorder()
744+ proxy.ServeHTTP(rw, req)
745+
746+ assert.Equal(t, http.StatusOK, rw.Code)
747+
748+ cleared := false
749+ for _, c := range rw.Result().Cookies() {
750+ if c.Name == proxy.CookieOptions.Name {
751+ cleared = true
752+ assert.Equal(t, "", c.Value)
753+ assert.Less(t, c.MaxAge, 0)
754+ }
755+ }
756+
757+ assert.True(t, cleared, "expected sign-in page to clear existing session cookie")
758+}
759+
716760func TestSignInPageIncludesTargetRedirect(t *testing.T) {
717761 sipTest, err := NewSignInPageTest(false)
718762 if err != nil {
@@ -850,7 +894,7 @@ func NewProcessCookieTest(opts ProcessCookieTestOpts, modifiers ...OptionsModifi
850894 // access_token validation.
851895 pcTest.proxy.CookieOptions.Refresh = time.Duration(0)
852896 pcTest.rw = httptest.NewRecorder()
853− pcTest.req, _ = http.NewRequest("GET", "/", strings.NewReader(""))
897+ pcTest.req, _ = http.NewRequest(http.MethodGet, "/", strings.NewReader(""))
854898 pcTest.validateUser = true
855899 return &pcTest, nil
856900}
@@ -983,7 +1027,7 @@ func NewUserInfoEndpointTest() (*ProcessCookieTest, error) {
9831027 if err != nil {
9841028 return nil, err
9851029 }
986− pcTest.req, _ = http.NewRequest("GET",
1030+ pcTest.req, _ = http.NewRequest(http.MethodGet,
9871031 pcTest.opts.ProxyPrefix+"/userinfo", nil)
9881032 return pcTest, nil
9891033}
@@ -1091,7 +1135,7 @@ func NewAuthOnlyEndpointTest(querystring string, modifiers ...OptionsModifier) (
10911135 return nil, err
10921136 }
10931137 pcTest.req, _ = http.NewRequest(
1094− "GET",
1138+ http.MethodGet,
10951139 fmt.Sprintf("%s/auth%s", pcTest.opts.ProxyPrefix, querystring),
10961140 nil)
10971141 return pcTest, nil
@@ -1230,7 +1274,7 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
12301274 pcTest.validateUser = true
12311275
12321276 pcTest.rw = httptest.NewRecorder()
1233− pcTest.req, _ = http.NewRequest("GET",
1277+ pcTest.req, _ = http.NewRequest(http.MethodGet,
12341278 pcTest.opts.ProxyPrefix+authOnlyPath, nil)
12351279
12361280 created := time.Now()
@@ -1323,7 +1367,7 @@ func TestAuthOnlyEndpointSetBasicAuthTrueRequestHeaders(t *testing.T) {
13231367 pcTest.validateUser = true
13241368
13251369 pcTest.rw = httptest.NewRecorder()
1326− pcTest.req, _ = http.NewRequest("GET",
1370+ pcTest.req, _ = http.NewRequest(http.MethodGet,
13271371 pcTest.opts.ProxyPrefix+authOnlyPath, nil)
13281372
13291373 created := time.Now()
@@ -1403,7 +1447,7 @@ func TestAuthOnlyEndpointSetBasicAuthFalseRequestHeaders(t *testing.T) {
14031447 pcTest.validateUser = true
14041448
14051449 pcTest.rw = httptest.NewRecorder()
1406− pcTest.req, _ = http.NewRequest("GET",
1450+ pcTest.req, _ = http.NewRequest(http.MethodGet,
14071451 pcTest.opts.ProxyPrefix+authOnlyPath, nil)
14081452
14091453 created := time.Now()
@@ -1451,7 +1495,7 @@ func TestAuthSkippedForPreflightRequests(t *testing.T) {
14511495 }
14521496 proxy.provider = NewTestProvider(upstreamURL, "")
14531497 rw := httptest.NewRecorder()
1454− req, _ := http.NewRequest("OPTIONS", "/preflight-request", nil)
1498+ req, _ := http.NewRequest(http.MethodOptions, "/preflight-request", nil)
14551499 proxy.ServeHTTP(rw, req)
14561500
14571501 assert.Equal(t, 200, rw.Code)
@@ -1608,19 +1652,19 @@ func TestRequestSignature(t *testing.T) {
16081652 resp string
16091653 }{
16101654 "No request signature": {
1611− method: "GET",
1655+ method: http.MethodGet,
16121656 body: "",
16131657 key: "",
16141658 resp: "no signature received",
16151659 },
16161660 "Get request": {
1617− method: "GET",
1661+ method: http.MethodGet,
16181662 body: "",
16191663 key: "7d9e1aa87a5954e6f9fc59266b3af9d7c35fda2d",
16201664 resp: "signatures match",
16211665 },
16221666 "Post request": {
1623− method: "POST",
1667+ method: http.MethodPost,
16241668 body: `{ "hello": "world!" }`,
16251669 key: "d90df39e2d19282840252612dd7c81421a372f61",
16261670 resp: "signatures match",
@@ -2145,7 +2189,33 @@ func TestTrustedIPs(t *testing.T) {
21452189 reverseProxy: false,
21462190 realClientIPHeader: "X-Real-IP", // Default value
21472191 req: func() *http.Request {
2148− req, _ := http.NewRequest("GET", "/", nil)
2192+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
2193+ return req
2194+ }(),
2195+ expectTrusted: false,
2196+ },
2197+ // Check Unix socket with no trusted IPs configured does not error.
2198+ {
2199+ name: "UnixSocketWithoutTrustedIPs",
2200+ trustedIPs: nil,
2201+ reverseProxy: false,
2202+ realClientIPHeader: "X-Real-IP",
2203+ req: func() *http.Request {
2204+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
2205+ req.RemoteAddr = "@"
2206+ return req
2207+ }(),
2208+ expectTrusted: false,
2209+ },
2210+ // Check Unix socket with trusted IPs configured returns false (no IP to match).
2211+ {
2212+ name: "UnixSocketWithTrustedIPs",
2213+ trustedIPs: []string{"127.0.0.1"},
2214+ reverseProxy: false,
2215+ realClientIPHeader: "X-Real-IP",
2216+ req: func() *http.Request {
2217+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
2218+ req.RemoteAddr = "@"
21492219 return req
21502220 }(),
21512221 expectTrusted: false,
@@ -2157,7 +2227,7 @@ func TestTrustedIPs(t *testing.T) {
21572227 reverseProxy: false,
21582228 realClientIPHeader: "X-Real-IP", // Default value
21592229 req: func() *http.Request {
2160− req, _ := http.NewRequest("GET", "/", nil)
2230+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
21612231 req.RemoteAddr = "127.0.0.1:43670"
21622232 return req
21632233 }(),
@@ -2170,7 +2240,7 @@ func TestTrustedIPs(t *testing.T) {
21702240 reverseProxy: true,
21712241 realClientIPHeader: "X-Real-IP", // Default value
21722242 req: func() *http.Request {
2173− req, _ := http.NewRequest("GET", "/", nil)
2243+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
21742244 req.RemoteAddr = "127.0.0.1:44324"
21752245 return req
21762246 }(),
@@ -2183,7 +2253,7 @@ func TestTrustedIPs(t *testing.T) {
21832253 reverseProxy: true,
21842254 realClientIPHeader: "X-Forwarded-For",
21852255 req: func() *http.Request {
2186− req, _ := http.NewRequest("GET", "/", nil)
2256+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
21872257 req.Header.Add("X-Forwarded-For", "127.0.0.1")
21882258 return req
21892259 }(),
@@ -2196,7 +2266,7 @@ func TestTrustedIPs(t *testing.T) {
21962266 reverseProxy: true,
21972267 realClientIPHeader: "X-Forwarded-For",
21982268 req: func() *http.Request {
2199− req, _ := http.NewRequest("GET", "/", nil)
2269+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
22002270 req.Header.Add("X-Forwarded-For", "::1")
22012271 return req
22022272 }(),
@@ -2209,7 +2279,7 @@ func TestTrustedIPs(t *testing.T) {
22092279 reverseProxy: true,
22102280 realClientIPHeader: "X-Forwarded-For",
22112281 req: func() *http.Request {
2212− req, _ := http.NewRequest("GET", "/", nil)
2282+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
22132283 req.Header.Add("X-Forwarded-For", "12.34.56.78")
22142284 return req
22152285 }(),
@@ -2222,7 +2292,7 @@ func TestTrustedIPs(t *testing.T) {
22222292 reverseProxy: true,
22232293 realClientIPHeader: "X-Forwarded-For",
22242294 req: func() *http.Request {
2225− req, _ := http.NewRequest("GET", "/", nil)
2295+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
22262296 req.Header.Add("X-Forwarded-For", "::2")
22272297 return req
22282298 }(),
@@ -2235,7 +2305,7 @@ func TestTrustedIPs(t *testing.T) {
22352305 reverseProxy: true,
22362306 realClientIPHeader: "X-Forwarded-For",
22372307 req: func() *http.Request {
2238− req, _ := http.NewRequest("GET", "/", nil)
2308+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
22392309 req.Header.Add("X-Real-IP", "::1")
22402310 return req
22412311 }(),
@@ -2248,7 +2318,7 @@ func TestTrustedIPs(t *testing.T) {
22482318 reverseProxy: true,
22492319 realClientIPHeader: "X-Forwarded-For",
22502320 req: func() *http.Request {
2251− req, _ := http.NewRequest("GET", "/", nil)
2321+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
22522322 req.Header.Add("X-Forwarded-For", "adsfljk29242as!!")
22532323 return req
22542324 }(),
@@ -2261,7 +2331,7 @@ func TestTrustedIPs(t *testing.T) {
22612331 reverseProxy: false,
22622332 realClientIPHeader: "X-Real-IP",
22632333 req: func() *http.Request {
2264− req, _ := http.NewRequest("GET", "/", nil)
2334+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
22652335 req.RemoteAddr = "adsfljk29242as!!"
22662336 return req
22672337 }(),
@@ -2357,12 +2427,12 @@ func Test_buildRoutesAllowlist(t *testing.T) {
23572427 },
23582428 expectedRoutes: []expectedAllowedRoute{
23592429 {
2360− method: "GET",
2430+ method: http.MethodGet,
23612431 negate: false,
23622432 regexString: "^/foo/bar",
23632433 },
23642434 {
2365− method: "POST",
2435+ method: http.MethodPost,
23662436 negate: false,
23672437 regexString: "^/baz/[0-9]+/thing",
23682438 },
@@ -2415,11 +2485,11 @@ func Test_buildRoutesAllowlist(t *testing.T) {
24152485 regexString: "^/baz/[0-9]+/thing/regex",
24162486 },
24172487 {
2418− method: "GET",
2488+ method: http.MethodGet,
24192489 regexString: "^/foo/bar",
24202490 },
24212491 {
2422− method: "POST",
2492+ method: http.MethodPost,
24232493 regexString: "^/baz/[0-9]+/thing",
24242494 },
24252495 {
@@ -2571,7 +2641,7 @@ func TestApiRoutes(t *testing.T) {
25712641
25722642 for _, tc := range testCases {
25732643 t.Run(tc.name, func(t *testing.T) {
2574− req, err := http.NewRequest("GET", tc.url, nil)
2644+ req, err := http.NewRequest(http.MethodGet, tc.url, nil)
25752645 req.Header.Set("Accept", tc.contentType)
25762646 assert.NoError(t, err)
25772647
@@ -2609,9 +2679,11 @@ func TestAllowedRequest(t *testing.T) {
26092679 }
26102680 opts.SkipAuthRegex = []string{
26112681 "^/skip/auth/regex$",
2682+ "^/public/.*/endpoint$",
26122683 }
26132684 opts.SkipAuthRoutes = []string{
26142685 "GET=^/skip/auth/routes/get",
2686+ "^/foo/.*/bar$",
26152687 }
26162688 err := validation.Validate(opts)
26172689 assert.NoError(t, err)
@@ -2628,25 +2700,37 @@ func TestAllowedRequest(t *testing.T) {
26282700 }{
26292701 {
26302702 name: "Regex GET allowed",
2631− method: "GET",
2703+ method: http.MethodGet,
26322704 url: "/skip/auth/regex",
26332705 allowed: true,
26342706 },
26352707 {
26362708 name: "Regex POST allowed ",
2637− method: "POST",
2709+ method: http.MethodPost,
26382710 url: "/skip/auth/regex",
26392711 allowed: true,
26402712 },
26412713 {
26422714 name: "Regex denied",
2643− method: "GET",
2715+ method: http.MethodGet,
26442716 url: "/wrong/denied",
26452717 allowed: false,
26462718 },
2719+ {
2720+ name: "Regex allowed with fragment-free path",
2721+ method: http.MethodGet,
2722+ url: "/public/legit/endpoint",
2723+ allowed: true,
2724+ },
2725+ {
2726+ name: "Regex denied when path contains encoded fragment suffix",
2727+ method: http.MethodGet,
2728+ url: "/public/secret%23/endpoint",
2729+ allowed: false,
2730+ },
26472731 {
26482732 name: "Route allowed",
2649− method: "GET",
2733+ method: http.MethodGet,
26502734 url: "/skip/auth/routes/get",
26512735 allowed: true,
26522736 },
@@ -2658,16 +2742,28 @@ func TestAllowedRequest(t *testing.T) {
26582742 },
26592743 {
26602744 name: "Route denied with wrong path",
2661− method: "GET",
2745+ method: http.MethodGet,
26622746 url: "/skip/auth/routes/wrong/path",
26632747 allowed: false,
26642748 },
26652749 {
26662750 name: "Route denied with wrong path and method",
2667− method: "POST",
2751+ method: http.MethodPost,
26682752 url: "/skip/auth/routes/wrong/path",
26692753 allowed: false,
26702754 },
2755+ {
2756+ name: "Route allowed with fragment-free path",
2757+ method: http.MethodGet,
2758+ url: "/foo/public/bar",
2759+ allowed: true,
2760+ },
2761+ {
2762+ name: "Route denied when path contains encoded fragment suffix",
2763+ method: http.MethodGet,
2764+ url: "/foo/secret%23/bar",
2765+ allowed: false,
2766+ },
26712767 }
26722768
26732769 for _, tc := range testCases {
@@ -2708,9 +2804,11 @@ func TestAllowedRequestWithForwardedUriHeader(t *testing.T) {
27082804 }
27092805 opts.SkipAuthRegex = []string{
27102806 "^/skip/auth/regex$",
2807+ "^/public/.*/endpoint$",
27112808 }
27122809 opts.SkipAuthRoutes = []string{
27132810 "GET=^/skip/auth/routes/get",
2811+ "^/foo/.*/bar$",
27142812 }
27152813 err := validation.Validate(opts)
27162814 assert.NoError(t, err)
@@ -2727,25 +2825,37 @@ func TestAllowedRequestWithForwardedUriHeader(t *testing.T) {
27272825 }{
27282826 {
27292827 name: "Regex GET allowed",
2730− method: "GET",
2828+ method: http.MethodGet,
27312829 url: "/skip/auth/regex",
27322830 allowed: true,
27332831 },
27342832 {
27352833 name: "Regex POST allowed ",
2736− method: "POST",
2834+ method: http.MethodPost,
27372835 url: "/skip/auth/regex",
27382836 allowed: true,
27392837 },
27402838 {
27412839 name: "Regex denied",
2742− method: "GET",
2840+ method: http.MethodGet,
27432841 url: "/wrong/denied",
27442842 allowed: false,
27452843 },
2844+ {
2845+ name: "Regex allowed with fragment-free path",
2846+ method: http.MethodGet,
2847+ url: "/public/legit/endpoint",
2848+ allowed: true,
2849+ },
2850+ {
2851+ name: "Regex denied when X-Forwarded-Uri contains an encoded fragment suffix",
2852+ method: http.MethodGet,
2853+ url: "/public/secret%23/endpoint",
2854+ allowed: false,
2855+ },
27462856 {
27472857 name: "Route allowed",
2748− method: "GET",
2858+ method: http.MethodGet,
27492859 url: "/skip/auth/routes/get",
27502860 allowed: true,
27512861 },
@@ -2757,22 +2867,35 @@ func TestAllowedRequestWithForwardedUriHeader(t *testing.T) {
27572867 },
27582868 {
27592869 name: "Route denied with wrong path",
2760− method: "GET",
2870+ method: http.MethodGet,
27612871 url: "/skip/auth/routes/wrong/path",
27622872 allowed: false,
27632873 },
27642874 {
27652875 name: "Route denied with wrong path and method",
2766− method: "POST",
2876+ method: http.MethodPost,
27672877 url: "/skip/auth/routes/wrong/path",
27682878 allowed: false,
27692879 },
2880+ {
2881+ name: "Route allowed with fragment-free path",
2882+ method: http.MethodGet,
2883+ url: "/foo/public/bar",
2884+ allowed: true,
2885+ },
2886+ {
2887+ name: "Route denied when X-Forwarded-Uri contains an encoded fragment suffix",
2888+ method: http.MethodGet,
2889+ url: "/foo/secret%23/bar",
2890+ allowed: false,
2891+ },
27702892 }
27712893
27722894 for _, tc := range testCases {
27732895 t.Run(tc.name, func(t *testing.T) {
27742896 req, err := http.NewRequest(tc.method, opts.ProxyPrefix+authOnlyPath, nil)
27752897 req.Header.Set("X-Forwarded-Uri", tc.url)
2898+ req.RemoteAddr = "127.0.0.1:4180"
27762899 assert.NoError(t, err)
27772900
27782901 rw := httptest.NewRecorder()
@@ -2787,6 +2910,43 @@ func TestAllowedRequestWithForwardedUriHeader(t *testing.T) {
27872910 }
27882911}
27892912
2913+func TestAllowedRequestWithForwardedUriHeaderRequiresTrustedProxy(t *testing.T) {
2914+ upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2915+ w.WriteHeader(200)
2916+ }))
2917+ t.Cleanup(upstreamServer.Close)
2918+
2919+ opts := baseTestOptions()
2920+ opts.ReverseProxy = true
2921+ opts.TrustedProxyIPs = []string{"127.0.0.1/32"}
2922+ opts.UpstreamServers = options.UpstreamConfig{
2923+ Upstreams: []options.Upstream{
2924+ {
2925+ ID: upstreamServer.URL,
2926+ Path: "/",
2927+ URI: upstreamServer.URL,
2928+ },
2929+ },
2930+ }
2931+ opts.SkipAuthRegex = []string{"^/skip/auth/regex$"}
2932+
2933+ err := validation.Validate(opts)
2934+ assert.NoError(t, err)
2935+
2936+ proxy, err := NewOAuthProxy(opts, func(_ string) bool { return true })
2937+ assert.NoError(t, err)
2938+
2939+ req, err := http.NewRequest(http.MethodGet, opts.ProxyPrefix+authOnlyPath, nil)
2940+ assert.NoError(t, err)
2941+ req.RemoteAddr = "192.0.2.10:4180"
2942+ req.Header.Set("X-Forwarded-Uri", "/skip/auth/regex")
2943+
2944+ rw := httptest.NewRecorder()
2945+ proxy.ServeHTTP(rw, req)
2946+
2947+ assert.Equal(t, 401, rw.Code)
2948+}
2949+
27902950func TestAllowedRequestNegateWithoutMethod(t *testing.T) {
27912951 upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
27922952 w.WriteHeader(200)
@@ -2826,37 +2986,37 @@ func TestAllowedRequestNegateWithoutMethod(t *testing.T) {
28262986 }{
28272987 {
28282988 name: "Some static file allowed",
2829− method: "GET",
2989+ method: http.MethodGet,
28302990 url: "/static/file.txt",
28312991 allowed: true,
28322992 },
28332993 {
28342994 name: "POST to contact form allowed",
2835− method: "POST",
2995+ method: http.MethodPost,
28362996 url: "/contact",
28372997 allowed: true,
28382998 },
28392999 {
28403000 name: "Regex POST allowed",
2841− method: "POST",
3001+ method: http.MethodPost,
28423002 url: "/api/public-entity",
28433003 allowed: true,
28443004 },
28453005 {
28463006 name: "Regex POST with trailing slash allowed",
2847− method: "POST",
3007+ method: http.MethodPost,
28483008 url: "/api/public-entity/",
28493009 allowed: true,
28503010 },
28513011 {
28523012 name: "Regex GET api route denied",
2853− method: "GET",
3013+ method: http.MethodGet,
28543014 url: "/api/users",
28553015 allowed: false,
28563016 },
28573017 {
28583018 name: "Regex POST api route denied",
2859− method: "POST",
3019+ method: http.MethodPost,
28603020 url: "/api/users",
28613021 allowed: false,
28623022 },
@@ -2926,37 +3086,37 @@ func TestAllowedRequestNegateWithMethod(t *testing.T) {
29263086 }{
29273087 {
29283088 name: "Some static file allowed",
2929− method: "GET",
3089+ method: http.MethodGet,
29303090 url: "/static/file.txt",
29313091 allowed: true,
29323092 },
29333093 {
29343094 name: "POST to contact form not allowed",
2935− method: "POST",
3095+ method: http.MethodPost,
29363096 url: "/contact",
29373097 allowed: false,
29383098 },
29393099 {
29403100 name: "Regex POST allowed",
2941− method: "POST",
3101+ method: http.MethodPost,
29423102 url: "/api/public-entity",
29433103 allowed: true,
29443104 },
29453105 {
29463106 name: "Regex POST with trailing slash allowed",
2947− method: "POST",
3107+ method: http.MethodPost,
29483108 url: "/api/public-entity/",
29493109 allowed: true,
29503110 },
29513111 {
29523112 name: "Regex GET api route denied",
2953− method: "GET",
3113+ method: http.MethodGet,
29543114 url: "/api/users",
29553115 allowed: false,
29563116 },
29573117 {
29583118 name: "Regex POST api route denied",
2959− method: "POST",
3119+ method: http.MethodPost,
29603120 url: "/api/users",
29613121 allowed: false,
29623122 },
@@ -3096,7 +3256,7 @@ func TestProxyAllowedGroups(t *testing.T) {
30963256 t.Fatal(err)
30973257 }
30983258
3099− test.req, _ = http.NewRequest("GET", fmt.Sprintf("/%s", tt.querystring), nil)
3259+ test.req, _ = http.NewRequest(http.MethodGet, fmt.Sprintf("/%s", tt.querystring), nil)
31003260
31013261 test.req.Header.Add("accept", applicationJSON)
31023262 err = test.SaveSession(session)
@@ -3240,7 +3400,7 @@ func TestAuthOnlyAllowedGroupsWithSkipMethods(t *testing.T) {
32403400 {
32413401 name: "UserWithGroupSkipAuthPreflight",
32423402 groups: []string{"a", "c"},
3243− method: "OPTIONS",
3403+ method: http.MethodOptions,
32443404 ip: "1.2.3.5:43670",
32453405 withSession: true,
32463406 expectedStatusCode: http.StatusAccepted,
@@ -3248,7 +3408,7 @@ func TestAuthOnlyAllowedGroupsWithSkipMethods(t *testing.T) {
32483408 {
32493409 name: "UserWithGroupTrustedIp",
32503410 groups: []string{"a", "c"},
3251− method: "GET",
3411+ method: http.MethodGet,
32523412 ip: "1.2.3.4:43670",
32533413 withSession: true,
32543414 expectedStatusCode: http.StatusAccepted,
@@ -3256,7 +3416,7 @@ func TestAuthOnlyAllowedGroupsWithSkipMethods(t *testing.T) {
32563416 {
32573417 name: "UserWithoutGroupSkipAuthPreflight",
32583418 groups: []string{"c"},
3259− method: "OPTIONS",
3419+ method: http.MethodOptions,
32603420 ip: "1.2.3.5:43670",
32613421 withSession: true,
32623422 expectedStatusCode: http.StatusForbidden,
@@ -3264,21 +3424,21 @@ func TestAuthOnlyAllowedGroupsWithSkipMethods(t *testing.T) {
32643424 {
32653425 name: "UserWithoutGroupTrustedIp",
32663426 groups: []string{"c"},
3267− method: "GET",
3427+ method: http.MethodGet,
32683428 ip: "1.2.3.4:43670",
32693429 withSession: true,
32703430 expectedStatusCode: http.StatusForbidden,
32713431 },
32723432 {
32733433 name: "UserWithoutSessionSkipAuthPreflight",
3274− method: "OPTIONS",
3434+ method: http.MethodOptions,
32753435 ip: "1.2.3.5:43670",
32763436 withSession: false,
32773437 expectedStatusCode: http.StatusAccepted,
32783438 },
32793439 {
32803440 name: "UserWithoutSessionTrustedIp",
3281− method: "GET",
3441+ method: http.MethodGet,
32823442 ip: "1.2.3.4:43670",
32833443 withSession: false,
32843444 expectedStatusCode: http.StatusAccepted,
@@ -3378,6 +3538,24 @@ func TestAuthOnlyAllowedEmailDomains(t *testing.T) {
33783538 querystring: "?allowed_email_domains=a.b.c.example.com,*.c.example.com",
33793539 expectedStatusCode: http.StatusAccepted,
33803540 },
3541+ {
3542+ name: "UserWithMultipleAtSignsExactDomain",
3543+ email: "attacker@evil.com@example.com",
3544+ querystring: "?allowed_email_domains=example.com",
3545+ expectedStatusCode: http.StatusForbidden,
3546+ },
3547+ {
3548+ name: "UserWithMultipleAtSignsWildcardDomain",
3549+ email: "attacker@evil.com@foo.example.com",
3550+ querystring: "?allowed_email_domains=*.example.com",
3551+ expectedStatusCode: http.StatusForbidden,
3552+ },
3553+ {
3554+ name: "UserWithMultipleAtSignsDotPrefixedDomain",
3555+ email: "attacker@evil.com@foo.example.com",
3556+ querystring: "?allowed_email_domains=.example.com",
3557+ expectedStatusCode: http.StatusForbidden,
3558+ },
33813559 }
33823560
33833561 for _, tc := range testCases {
@@ -3612,14 +3790,14 @@ func TestIdTokenPlaceholderInSignOut(t *testing.T) {
36123790
36133791 // Save the required session
36143792 rw := httptest.NewRecorder()
3615− req, _ := http.NewRequest("GET", "/", nil)
3793+ req, _ := http.NewRequest(http.MethodGet, "/", nil)
36163794 err = proxy.sessionStore.Save(rw, req, session)
36173795 assert.NoError(t, err)
36183796
36193797 rw = httptest.NewRecorder()
36203798
36213799 rdUrl := url.QueryEscape("https://my-oidc-provider.example.com/sign_out_page?id_token_hint={id_token}&post_logout_redirect_uri=https://my-app.example.com/")
3622− req, _ = http.NewRequest("GET", "/oauth2/sign_out?rd="+rdUrl, nil)
3800+ req, _ = http.NewRequest(http.MethodGet, "/oauth2/sign_out?rd="+rdUrl, nil)
36233801 req = middlewareapi.AddRequestScope(req, &middlewareapi.RequestScope{
36243802 RequestID: "11111111-2222-4333-8444-555555555555",
36253803 Session: session,