@@ -15,16 +15,14 @@ import (
17 "github.com/coreos/go-oidc/v3/oidc"
17 "github.com/coreos/go-oidc/v3/oidc"
18− middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
18+ "github.com/mbland/hmacauth"
19 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
19 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
20 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
20 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
21− "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/authentication/hmacauth"
22 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/cookies"
21 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/cookies"
23 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
22 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
24 internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
23 internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
25 sessionscookie "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/sessions/cookie"
24 sessionscookie "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/sessions/cookie"
26 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/upstream"
25 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/upstream"
27− "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
28 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/validation"
26 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/validation"
29 "github.com/oauth2-proxy/oauth2-proxy/v7/providers"
27 "github.com/oauth2-proxy/oauth2-proxy/v7/providers"
30 "github.com/stretchr/testify/assert"
28 "github.com/stretchr/testify/assert"
@@ -54,7 +52,7 @@ func TestRobotsTxt(t *testing.T) {
54 t.Fatal(err)
52 t.Fatal(err)
56 rw := httptest.NewRecorder()
54 rw := httptest.NewRecorder()
57− req, _ := http.NewRequest(http.MethodGet, "/robots.txt", nil)
55+ req, _ := http.NewRequest("GET", "/robots.txt", nil)
58 proxy.ServeHTTP(rw, req)
56 proxy.ServeHTTP(rw, req)
59 assert.Equal(t, 200, rw.Code)
57 assert.Equal(t, 200, rw.Code)
60 assert.Equal(t, "User-agent: *\nDisallow: /\n", rw.Body.String())
58 assert.Equal(t, "User-agent: *\nDisallow: /\n", rw.Body.String())
@@ -241,7 +239,7 @@ func TestBasicAuthPassword(t *testing.T) {
242 // Save the required session
240 // Save the required session
243 rw := httptest.NewRecorder()
241 rw := httptest.NewRecorder()
244− req, _ := http.NewRequest(http.MethodGet, "/", nil)
242+ req, _ := http.NewRequest("GET", "/", nil)
245 err = proxy.sessionStore.Save(rw, req, &sessions.SessionState{
243 err = proxy.sessionStore.Save(rw, req, &sessions.SessionState{
246 Email: emailAddress,
244 Email: emailAddress,
@@ -250,7 +248,7 @@ func TestBasicAuthPassword(t *testing.T) {
250 // Extract the cookie value to inject into the test request
248 // Extract the cookie value to inject into the test request
251 cookie := rw.Header().Values("Set-Cookie")[0]
249 cookie := rw.Header().Values("Set-Cookie")[0]
253− req, _ = http.NewRequest(http.MethodGet, "/", nil)
251+ req, _ = http.NewRequest("GET", "/", nil)
254 req.Header.Set("Cookie", cookie)
252 req.Header.Set("Cookie", cookie)
255 rw = httptest.NewRecorder()
253 rw = httptest.NewRecorder()
256 proxy.ServeHTTP(rw, req)
254 proxy.ServeHTTP(rw, req)
@@ -300,14 +298,14 @@ func TestPassGroupsHeadersWithGroups(t *testing.T) {
301 // Save the required session
299 // Save the required session
302 rw := httptest.NewRecorder()
300 rw := httptest.NewRecorder()
303− req, _ := http.NewRequest(http.MethodGet, "/", nil)
301+ req, _ := http.NewRequest("GET", "/", nil)
304 err = proxy.sessionStore.Save(rw, req, session)
302 err = proxy.sessionStore.Save(rw, req, session)
305 assert.NoError(t, err)
303 assert.NoError(t, err)
307 // Extract the cookie value to inject into the test request
305 // Extract the cookie value to inject into the test request
308 cookie := rw.Header().Values("Set-Cookie")[0]
306 cookie := rw.Header().Values("Set-Cookie")[0]
310− req, _ = http.NewRequest(http.MethodGet, "/", nil)
308+ req, _ = http.NewRequest("GET", "/", nil)
311 req.Header.Set("Cookie", cookie)
309 req.Header.Set("Cookie", cookie)
312 rw = httptest.NewRecorder()
310 rw = httptest.NewRecorder()
313 proxy.ServeHTTP(rw, req)
311 proxy.ServeHTTP(rw, req)
@@ -457,7 +455,7 @@ func (patTest *PassAccessTokenTest) getEndpointWithCookie(cookie string, endpoin
457 return 0, ""
455 return 0, ""
460− req, err := http.NewRequest(http.MethodGet, endpoint, strings.NewReader(""))
458+ req, err := http.NewRequest("GET", endpoint, strings.NewReader(""))
461 if err != nil {
459 if err != nil {
462 return 0, ""
460 return 0, ""
@@ -508,7 +506,7 @@ func TestStaticProxyUpstream(t *testing.T) {
508 ProxyUpstream: options.Upstream{
506 ProxyUpstream: options.Upstream{
509 ID: "static-proxy",
507 ID: "static-proxy",
510 Path: "/static-proxy",
508 Path: "/static-proxy",
511− Static: ptr.To(true),
509+ Static: true,
514 if err != nil {
512 if err != nil {
@@ -608,7 +606,7 @@ func NewSignInPageTest(skipProvider bool) (*SignInPageTest, error) {
609func (sipTest *SignInPageTest) GetEndpoint(endpoint string) (int, string) {
607func (sipTest *SignInPageTest) GetEndpoint(endpoint string) (int, string) {
610 rw := httptest.NewRecorder()
608 rw := httptest.NewRecorder()
611− req, _ := http.NewRequest(http.MethodGet, endpoint, strings.NewReader(""))
609+ req, _ := http.NewRequest("GET", endpoint, strings.NewReader(""))
612 sipTest.proxy.ServeHTTP(rw, req)
610 sipTest.proxy.ServeHTTP(rw, req)
613 return rw.Code, rw.Body.String()
611 return rw.Code, rw.Body.String()
@@ -713,50 +711,6 @@ func TestManualSignInCorrectCredentials(t *testing.T) {
713 assert.Equal(t, http.StatusFound, statusCode)
711 assert.Equal(t, http.StatusFound, statusCode)
716−func TestSignInPageClearsExistingSessionCookie(t *testing.T) {
717− opts := baseTestOptions()
718− err := validation.Validate(opts)
719− require.NoError(t, err)
721− proxy, err := NewOAuthProxy(opts, func(string) bool {
724− require.NoError(t, err)
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",
732− require.NoError(t, err)
734− cookies := saveRW.Result().Cookies()
735− require.NotEmpty(t, cookies)
737− // Send that cookie to the sign-in page.
738− req := httptest.NewRequest(http.MethodGet, "/oauth2/sign_in", nil)
739− for _, c := range cookies {
743− rw := httptest.NewRecorder()
744− proxy.ServeHTTP(rw, req)
746− assert.Equal(t, http.StatusOK, rw.Code)
749− for _, c := range rw.Result().Cookies() {
750− if c.Name == proxy.CookieOptions.Name {
752− assert.Equal(t, "", c.Value)
753− assert.Less(t, c.MaxAge, 0)
757− assert.True(t, cleared, "expected sign-in page to clear existing session cookie")
760func TestSignInPageIncludesTargetRedirect(t *testing.T) {
714func TestSignInPageIncludesTargetRedirect(t *testing.T) {
761 sipTest, err := NewSignInPageTest(false)
715 sipTest, err := NewSignInPageTest(false)
762 if err != nil {
716 if err != nil {
@@ -894,7 +848,7 @@ func NewProcessCookieTest(opts ProcessCookieTestOpts, modifiers ...OptionsModifi
894 // access_token validation.
848 // access_token validation.
895 pcTest.proxy.CookieOptions.Refresh = time.Duration(0)
849 pcTest.proxy.CookieOptions.Refresh = time.Duration(0)
896 pcTest.rw = httptest.NewRecorder()
850 pcTest.rw = httptest.NewRecorder()
897− pcTest.req, _ = http.NewRequest(http.MethodGet, "/", strings.NewReader(""))
851+ pcTest.req, _ = http.NewRequest("GET", "/", strings.NewReader(""))
898 pcTest.validateUser = true
852 pcTest.validateUser = true
899 return &pcTest, nil
853 return &pcTest, nil
@@ -1027,7 +981,7 @@ func NewUserInfoEndpointTest() (*ProcessCookieTest, error) {
1027 if err != nil {
981 if err != nil {
1028 return nil, err
982 return nil, err
1030− pcTest.req, _ = http.NewRequest(http.MethodGet,
984+ pcTest.req, _ = http.NewRequest("GET",
1031 pcTest.opts.ProxyPrefix+"/userinfo", nil)
985 pcTest.opts.ProxyPrefix+"/userinfo", nil)
1032 return pcTest, nil
986 return pcTest, nil
@@ -1077,20 +1031,6 @@ func TestUserInfoEndpointAccepted(t *testing.T) {
1078 expectedResponse: "{\"user\":\"john.doe\",\"email\":\"john.doe@example.com\",\"groups\":[\"example\",\"groups\"],\"preferredUsername\":\"john\"}\n",
1032 expectedResponse: "{\"user\":\"john.doe\",\"email\":\"john.doe@example.com\",\"groups\":[\"example\",\"groups\"],\"preferredUsername\":\"john\"}\n",
1081− name: "With Additional Claim",
1082− session: &sessions.SessionState{
1084− PreferredUsername: "john",
1085− Email: "john.doe@example.com",
1086− Groups: []string{"example", "groups"},
1087− AccessToken: "my_access_token",
1088− AdditionalClaims: map[string]interface{}{
1092− expectedResponse: "{\"user\":\"john.doe\",\"email\":\"john.doe@example.com\",\"groups\":[\"example\",\"groups\"],\"preferredUsername\":\"john\",\"additionalClaims\":{\"foo\":\"bar\"}}\n",
1096 for _, tc := range testCases {
1036 for _, tc := range testCases {
@@ -1135,7 +1075,7 @@ func NewAuthOnlyEndpointTest(querystring string, modifiers ...OptionsModifier) (
1135 return nil, err
1075 return nil, err
1137 pcTest.req, _ = http.NewRequest(
1077 pcTest.req, _ = http.NewRequest(
1138− http.MethodGet,
1078+ "GET",
1139 fmt.Sprintf("%s/auth%s", pcTest.opts.ProxyPrefix, querystring),
1079 fmt.Sprintf("%s/auth%s", pcTest.opts.ProxyPrefix, querystring),
1141 return pcTest, nil
1081 return pcTest, nil
@@ -1274,7 +1214,7 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
1274 pcTest.validateUser = true
1214 pcTest.validateUser = true
1276 pcTest.rw = httptest.NewRecorder()
1216 pcTest.rw = httptest.NewRecorder()
1277− pcTest.req, _ = http.NewRequest(http.MethodGet,
1217+ pcTest.req, _ = http.NewRequest("GET",
1278 pcTest.opts.ProxyPrefix+authOnlyPath, nil)
1218 pcTest.opts.ProxyPrefix+authOnlyPath, nil)
1280 created := time.Now()
1220 created := time.Now()
@@ -1367,7 +1307,7 @@ func TestAuthOnlyEndpointSetBasicAuthTrueRequestHeaders(t *testing.T) {
1367 pcTest.validateUser = true
1307 pcTest.validateUser = true
1369 pcTest.rw = httptest.NewRecorder()
1309 pcTest.rw = httptest.NewRecorder()
1370− pcTest.req, _ = http.NewRequest(http.MethodGet,
1310+ pcTest.req, _ = http.NewRequest("GET",
1371 pcTest.opts.ProxyPrefix+authOnlyPath, nil)
1311 pcTest.opts.ProxyPrefix+authOnlyPath, nil)
1373 created := time.Now()
1313 created := time.Now()
@@ -1447,7 +1387,7 @@ func TestAuthOnlyEndpointSetBasicAuthFalseRequestHeaders(t *testing.T) {
1447 pcTest.validateUser = true
1387 pcTest.validateUser = true
1449 pcTest.rw = httptest.NewRecorder()
1389 pcTest.rw = httptest.NewRecorder()
1450− pcTest.req, _ = http.NewRequest(http.MethodGet,
1390+ pcTest.req, _ = http.NewRequest("GET",
1451 pcTest.opts.ProxyPrefix+authOnlyPath, nil)
1391 pcTest.opts.ProxyPrefix+authOnlyPath, nil)
1453 created := time.Now()
1393 created := time.Now()
@@ -1495,7 +1435,7 @@ func TestAuthSkippedForPreflightRequests(t *testing.T) {
1496 proxy.provider = NewTestProvider(upstreamURL, "")
1436 proxy.provider = NewTestProvider(upstreamURL, "")
1497 rw := httptest.NewRecorder()
1437 rw := httptest.NewRecorder()
1498− req, _ := http.NewRequest(http.MethodOptions, "/preflight-request", nil)
1438+ req, _ := http.NewRequest("OPTIONS", "/preflight-request", nil)
1499 proxy.ServeHTTP(rw, req)
1439 proxy.ServeHTTP(rw, req)
1501 assert.Equal(t, 200, rw.Code)
1441 assert.Equal(t, 200, rw.Code)
@@ -1652,19 +1592,19 @@ func TestRequestSignature(t *testing.T) {
1652 resp string
1592 resp string
1654 "No request signature": {
1594 "No request signature": {
1655− method: http.MethodGet,
1595+ method: "GET",
1656 body: "",
1596 body: "",
1657 key: "",
1597 key: "",
1658 resp: "no signature received",
1598 resp: "no signature received",
1660 "Get request": {
1600 "Get request": {
1661− method: http.MethodGet,
1601+ method: "GET",
1662 body: "",
1602 body: "",
1663 key: "7d9e1aa87a5954e6f9fc59266b3af9d7c35fda2d",
1603 key: "7d9e1aa87a5954e6f9fc59266b3af9d7c35fda2d",
1664 resp: "signatures match",
1604 resp: "signatures match",
1666 "Post request": {
1606 "Post request": {
1667− method: http.MethodPost,
1607+ method: "POST",
1668 body: `{ "hello": "world!" }`,
1608 body: `{ "hello": "world!" }`,
1669 key: "d90df39e2d19282840252612dd7c81421a372f61",
1609 key: "d90df39e2d19282840252612dd7c81421a372f61",
1670 resp: "signatures match",
1610 resp: "signatures match",
@@ -2087,44 +2027,6 @@ func Test_noCacheHeaders(t *testing.T) {
2090−func TestSignOutCallsBackendLogoutURL(t *testing.T) {
2091− const testIDToken = "test-id-token-12345"
2092− var receivedURL string
2093− backendLogoutServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
2094− receivedURL = req.URL.String()
2095− rw.WriteHeader(http.StatusOK)
2097− defer backendLogoutServer.Close()
2099− opts := baseTestOptions()
2100− opts.Providers[0].BackendLogoutURL = backendLogoutServer.URL + "/logout?id_token_hint={id_token}"
2101− err := validation.Validate(opts)
2102− require.NoError(t, err)
2104− proxy, err := NewOAuthProxy(opts, func(string) bool { return true })
2105− require.NoError(t, err)
2107− // Save a session with IDToken so backend logout can use it
2108− rw := httptest.NewRecorder()
2109− req := httptest.NewRequest(http.MethodGet, "/", nil)
2110− err = proxy.sessionStore.Save(rw, req, &sessions.SessionState{
2111− Email: "user@example.com",
2112− IDToken: testIDToken,
2114− require.NoError(t, err)
2115− cookie := rw.Header().Values("Set-Cookie")[0]
2117− // Hit sign_out with the session cookie; backend logout should be called before session is cleared
2118− signOutReq := httptest.NewRequest(http.MethodGet, "/oauth2/sign_out", nil)
2119− signOutReq.Header.Set("Cookie", cookie)
2120− rec := httptest.NewRecorder()
2121− proxy.ServeHTTP(rec, signOutReq)
2123− assert.Equal(t, http.StatusFound, rec.Code, "sign_out should redirect")
2124− assert.Contains(t, receivedURL, "id_token_hint="+testIDToken,
2125− "backend logout URL should have been called with id_token from session")
2128func baseTestOptions() *options.Options {
2030func baseTestOptions() *options.Options {
2129 opts := options.NewOptions()
2031 opts := options.NewOptions()
2130 opts.Cookie.Secret = rawCookieSecret
2032 opts.Cookie.Secret = rawCookieSecret
@@ -2189,33 +2091,7 @@ func TestTrustedIPs(t *testing.T) {
2189 reverseProxy: false,
2091 reverseProxy: false,
2190 realClientIPHeader: "X-Real-IP", // Default value
2092 realClientIPHeader: "X-Real-IP", // Default value
2191 req: func() *http.Request {
2093 req: func() *http.Request {
2192− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2094+ req, _ := http.NewRequest("GET", "/", nil)
2195− expectTrusted: false,
2197− // Check Unix socket with no trusted IPs configured does not error.
2199− name: "UnixSocketWithoutTrustedIPs",
2201− reverseProxy: false,
2202− realClientIPHeader: "X-Real-IP",
2203− req: func() *http.Request {
2204− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2205− req.RemoteAddr = "@"
2208− expectTrusted: false,
2210− // Check Unix socket with trusted IPs configured returns false (no IP to match).
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 = "@"
2219 return req
2095 return req
2221 expectTrusted: false,
2097 expectTrusted: false,
@@ -2227,7 +2103,7 @@ func TestTrustedIPs(t *testing.T) {
2227 reverseProxy: false,
2103 reverseProxy: false,
2228 realClientIPHeader: "X-Real-IP", // Default value
2104 realClientIPHeader: "X-Real-IP", // Default value
2229 req: func() *http.Request {
2105 req: func() *http.Request {
2230− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2106+ req, _ := http.NewRequest("GET", "/", nil)
2231 req.RemoteAddr = "127.0.0.1:43670"
2107 req.RemoteAddr = "127.0.0.1:43670"
2232 return req
2108 return req
@@ -2240,7 +2116,7 @@ func TestTrustedIPs(t *testing.T) {
2240 reverseProxy: true,
2116 reverseProxy: true,
2241 realClientIPHeader: "X-Real-IP", // Default value
2117 realClientIPHeader: "X-Real-IP", // Default value
2242 req: func() *http.Request {
2118 req: func() *http.Request {
2243− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2119+ req, _ := http.NewRequest("GET", "/", nil)
2244 req.RemoteAddr = "127.0.0.1:44324"
2120 req.RemoteAddr = "127.0.0.1:44324"
2245 return req
2121 return req
@@ -2253,7 +2129,7 @@ func TestTrustedIPs(t *testing.T) {
2253 reverseProxy: true,
2129 reverseProxy: true,
2254 realClientIPHeader: "X-Forwarded-For",
2130 realClientIPHeader: "X-Forwarded-For",
2255 req: func() *http.Request {
2131 req: func() *http.Request {
2256− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2132+ req, _ := http.NewRequest("GET", "/", nil)
2257 req.Header.Add("X-Forwarded-For", "127.0.0.1")
2133 req.Header.Add("X-Forwarded-For", "127.0.0.1")
2258 return req
2134 return req
@@ -2266,7 +2142,7 @@ func TestTrustedIPs(t *testing.T) {
2266 reverseProxy: true,
2142 reverseProxy: true,
2267 realClientIPHeader: "X-Forwarded-For",
2143 realClientIPHeader: "X-Forwarded-For",
2268 req: func() *http.Request {
2144 req: func() *http.Request {
2269− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2145+ req, _ := http.NewRequest("GET", "/", nil)
2270 req.Header.Add("X-Forwarded-For", "::1")
2146 req.Header.Add("X-Forwarded-For", "::1")
2271 return req
2147 return req
@@ -2279,7 +2155,7 @@ func TestTrustedIPs(t *testing.T) {
2279 reverseProxy: true,
2155 reverseProxy: true,
2280 realClientIPHeader: "X-Forwarded-For",
2156 realClientIPHeader: "X-Forwarded-For",
2281 req: func() *http.Request {
2157 req: func() *http.Request {
2282− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2158+ req, _ := http.NewRequest("GET", "/", nil)
2283 req.Header.Add("X-Forwarded-For", "12.34.56.78")
2159 req.Header.Add("X-Forwarded-For", "12.34.56.78")
2284 return req
2160 return req
@@ -2292,7 +2168,7 @@ func TestTrustedIPs(t *testing.T) {
2292 reverseProxy: true,
2168 reverseProxy: true,
2293 realClientIPHeader: "X-Forwarded-For",
2169 realClientIPHeader: "X-Forwarded-For",
2294 req: func() *http.Request {
2170 req: func() *http.Request {
2295− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2171+ req, _ := http.NewRequest("GET", "/", nil)
2296 req.Header.Add("X-Forwarded-For", "::2")
2172 req.Header.Add("X-Forwarded-For", "::2")
2297 return req
2173 return req
@@ -2305,7 +2181,7 @@ func TestTrustedIPs(t *testing.T) {
2305 reverseProxy: true,
2181 reverseProxy: true,
2306 realClientIPHeader: "X-Forwarded-For",
2182 realClientIPHeader: "X-Forwarded-For",
2307 req: func() *http.Request {
2183 req: func() *http.Request {
2308− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2184+ req, _ := http.NewRequest("GET", "/", nil)
2309 req.Header.Add("X-Real-IP", "::1")
2185 req.Header.Add("X-Real-IP", "::1")
2310 return req
2186 return req
@@ -2318,7 +2194,7 @@ func TestTrustedIPs(t *testing.T) {
2318 reverseProxy: true,
2194 reverseProxy: true,
2319 realClientIPHeader: "X-Forwarded-For",
2195 realClientIPHeader: "X-Forwarded-For",
2320 req: func() *http.Request {
2196 req: func() *http.Request {
2321− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2197+ req, _ := http.NewRequest("GET", "/", nil)
2322 req.Header.Add("X-Forwarded-For", "adsfljk29242as!!")
2198 req.Header.Add("X-Forwarded-For", "adsfljk29242as!!")
2323 return req
2199 return req
@@ -2331,7 +2207,7 @@ func TestTrustedIPs(t *testing.T) {
2331 reverseProxy: false,
2207 reverseProxy: false,
2332 realClientIPHeader: "X-Real-IP",
2208 realClientIPHeader: "X-Real-IP",
2333 req: func() *http.Request {
2209 req: func() *http.Request {
2334− req, _ := http.NewRequest(http.MethodGet, "/", nil)
2210+ req, _ := http.NewRequest("GET", "/", nil)
2335 req.RemoteAddr = "adsfljk29242as!!"
2211 req.RemoteAddr = "adsfljk29242as!!"
2336 return req
2212 return req
@@ -2347,7 +2223,7 @@ func TestTrustedIPs(t *testing.T) {
2348 ID: "static",
2224 ID: "static",
2349 Path: "/",
2225 Path: "/",
2350− Static: ptr.To(true),
2226+ Static: true,
@@ -2427,12 +2303,12 @@ func Test_buildRoutesAllowlist(t *testing.T) {
2428 expectedRoutes: []expectedAllowedRoute{
2304 expectedRoutes: []expectedAllowedRoute{
2430− method: http.MethodGet,
2306+ method: "GET",
2431 negate: false,
2307 negate: false,
2432 regexString: "^/foo/bar",
2308 regexString: "^/foo/bar",
2435− method: http.MethodPost,
2311+ method: "POST",
2436 negate: false,
2312 negate: false,
2437 regexString: "^/baz/[0-9]+/thing",
2313 regexString: "^/baz/[0-9]+/thing",
@@ -2485,11 +2361,11 @@ func Test_buildRoutesAllowlist(t *testing.T) {
2485 regexString: "^/baz/[0-9]+/thing/regex",
2361 regexString: "^/baz/[0-9]+/thing/regex",
2488− method: http.MethodGet,
2364+ method: "GET",
2489 regexString: "^/foo/bar",
2365 regexString: "^/foo/bar",
2492− method: http.MethodPost,
2368+ method: "POST",
2493 regexString: "^/baz/[0-9]+/thing",
2369 regexString: "^/baz/[0-9]+/thing",
@@ -2641,7 +2517,7 @@ func TestApiRoutes(t *testing.T) {
2642 for _, tc := range testCases {
2518 for _, tc := range testCases {
2643 t.Run(tc.name, func(t *testing.T) {
2519 t.Run(tc.name, func(t *testing.T) {
2644− req, err := http.NewRequest(http.MethodGet, tc.url, nil)
2520+ req, err := http.NewRequest("GET", tc.url, nil)
2645 req.Header.Set("Accept", tc.contentType)
2521 req.Header.Set("Accept", tc.contentType)
2646 assert.NoError(t, err)
2522 assert.NoError(t, err)
@@ -2679,11 +2555,9 @@ func TestAllowedRequest(t *testing.T) {
2680 opts.SkipAuthRegex = []string{
2556 opts.SkipAuthRegex = []string{
2681 "^/skip/auth/regex$",
2557 "^/skip/auth/regex$",
2682− "^/public/.*/endpoint$",
2684 opts.SkipAuthRoutes = []string{
2559 opts.SkipAuthRoutes = []string{
2685 "GET=^/skip/auth/routes/get",
2560 "GET=^/skip/auth/routes/get",
2688 err := validation.Validate(opts)
2562 err := validation.Validate(opts)
2689 assert.NoError(t, err)
2563 assert.NoError(t, err)
@@ -2700,37 +2574,25 @@ func TestAllowedRequest(t *testing.T) {
2702 name: "Regex GET allowed",
2576 name: "Regex GET allowed",
2703− method: http.MethodGet,
2577+ method: "GET",
2704 url: "/skip/auth/regex",
2578 url: "/skip/auth/regex",
2705 allowed: true,
2579 allowed: true,
2708 name: "Regex POST allowed ",
2582 name: "Regex POST allowed ",
2709− method: http.MethodPost,
2583+ method: "POST",
2710 url: "/skip/auth/regex",
2584 url: "/skip/auth/regex",
2711 allowed: true,
2585 allowed: true,
2714 name: "Regex denied",
2588 name: "Regex denied",
2715− method: http.MethodGet,
2589+ method: "GET",
2716 url: "/wrong/denied",
2590 url: "/wrong/denied",
2717 allowed: false,
2591 allowed: false,
2720− name: "Regex allowed with fragment-free path",
2721− method: http.MethodGet,
2722− url: "/public/legit/endpoint",
2726− name: "Regex denied when path contains encoded fragment suffix",
2727− method: http.MethodGet,
2728− url: "/public/secret%23/endpoint",
2732 name: "Route allowed",
2594 name: "Route allowed",
2733− method: http.MethodGet,
2595+ method: "GET",
2734 url: "/skip/auth/routes/get",
2596 url: "/skip/auth/routes/get",
2735 allowed: true,
2597 allowed: true,
@@ -2742,28 +2604,16 @@ func TestAllowedRequest(t *testing.T) {
2744 name: "Route denied with wrong path",
2606 name: "Route denied with wrong path",
2745− method: http.MethodGet,
2607+ method: "GET",
2746 url: "/skip/auth/routes/wrong/path",
2608 url: "/skip/auth/routes/wrong/path",
2747 allowed: false,
2609 allowed: false,
2750 name: "Route denied with wrong path and method",
2612 name: "Route denied with wrong path and method",
2751− method: http.MethodPost,
2613+ method: "POST",
2752 url: "/skip/auth/routes/wrong/path",
2614 url: "/skip/auth/routes/wrong/path",
2753 allowed: false,
2615 allowed: false,
2756− name: "Route allowed with fragment-free path",
2757− method: http.MethodGet,
2758− url: "/foo/public/bar",
2762− name: "Route denied when path contains encoded fragment suffix",
2763− method: http.MethodGet,
2764− url: "/foo/secret%23/bar",
2769 for _, tc := range testCases {
2619 for _, tc := range testCases {
@@ -2804,11 +2654,9 @@ func TestAllowedRequestWithForwardedUriHeader(t *testing.T) {
2805 opts.SkipAuthRegex = []string{
2655 opts.SkipAuthRegex = []string{
2806 "^/skip/auth/regex$",
2656 "^/skip/auth/regex$",
2807− "^/public/.*/endpoint$",
2809 opts.SkipAuthRoutes = []string{
2658 opts.SkipAuthRoutes = []string{
2810 "GET=^/skip/auth/routes/get",
2659 "GET=^/skip/auth/routes/get",
2813 err := validation.Validate(opts)
2661 err := validation.Validate(opts)
2814 assert.NoError(t, err)
2662 assert.NoError(t, err)
@@ -2825,37 +2673,25 @@ func TestAllowedRequestWithForwardedUriHeader(t *testing.T) {
2827 name: "Regex GET allowed",
2675 name: "Regex GET allowed",
2828− method: http.MethodGet,
2676+ method: "GET",
2829 url: "/skip/auth/regex",
2677 url: "/skip/auth/regex",
2830 allowed: true,
2678 allowed: true,
2833 name: "Regex POST allowed ",
2681 name: "Regex POST allowed ",
2834− method: http.MethodPost,
2682+ method: "POST",
2835 url: "/skip/auth/regex",
2683 url: "/skip/auth/regex",
2836 allowed: true,
2684 allowed: true,
2839 name: "Regex denied",
2687 name: "Regex denied",
2840− method: http.MethodGet,
2688+ method: "GET",
2841 url: "/wrong/denied",
2689 url: "/wrong/denied",
2842 allowed: false,
2690 allowed: false,
2845− name: "Regex allowed with fragment-free path",
2846− method: http.MethodGet,
2847− url: "/public/legit/endpoint",
2851− name: "Regex denied when X-Forwarded-Uri contains an encoded fragment suffix",
2852− method: http.MethodGet,
2853− url: "/public/secret%23/endpoint",
2857 name: "Route allowed",
2693 name: "Route allowed",
2858− method: http.MethodGet,
2694+ method: "GET",
2859 url: "/skip/auth/routes/get",
2695 url: "/skip/auth/routes/get",
2860 allowed: true,
2696 allowed: true,
@@ -2867,35 +2703,22 @@ func TestAllowedRequestWithForwardedUriHeader(t *testing.T) {
2869 name: "Route denied with wrong path",
2705 name: "Route denied with wrong path",
2870− method: http.MethodGet,
2706+ method: "GET",
2871 url: "/skip/auth/routes/wrong/path",
2707 url: "/skip/auth/routes/wrong/path",
2872 allowed: false,
2708 allowed: false,
2875 name: "Route denied with wrong path and method",
2711 name: "Route denied with wrong path and method",
2876− method: http.MethodPost,
2712+ method: "POST",
2877 url: "/skip/auth/routes/wrong/path",
2713 url: "/skip/auth/routes/wrong/path",
2878 allowed: false,
2714 allowed: false,
2881− name: "Route allowed with fragment-free path",
2882− method: http.MethodGet,
2883− url: "/foo/public/bar",
2887− name: "Route denied when X-Forwarded-Uri contains an encoded fragment suffix",
2888− method: http.MethodGet,
2889− url: "/foo/secret%23/bar",
2894 for _, tc := range testCases {
2718 for _, tc := range testCases {
2895 t.Run(tc.name, func(t *testing.T) {
2719 t.Run(tc.name, func(t *testing.T) {
2896 req, err := http.NewRequest(tc.method, opts.ProxyPrefix+authOnlyPath, nil)
2720 req, err := http.NewRequest(tc.method, opts.ProxyPrefix+authOnlyPath, nil)
2897 req.Header.Set("X-Forwarded-Uri", tc.url)
2721 req.Header.Set("X-Forwarded-Uri", tc.url)
2898− req.RemoteAddr = "127.0.0.1:4180"
2899 assert.NoError(t, err)
2722 assert.NoError(t, err)
2901 rw := httptest.NewRecorder()
2724 rw := httptest.NewRecorder()
@@ -2910,43 +2733,6 @@ func TestAllowedRequestWithForwardedUriHeader(t *testing.T) {
2913−func TestAllowedRequestWithForwardedUriHeaderRequiresTrustedProxy(t *testing.T) {
2914− upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2917− t.Cleanup(upstreamServer.Close)
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{
2925− ID: upstreamServer.URL,
2927− URI: upstreamServer.URL,
2931− opts.SkipAuthRegex = []string{"^/skip/auth/regex$"}
2933− err := validation.Validate(opts)
2934− assert.NoError(t, err)
2936− proxy, err := NewOAuthProxy(opts, func(_ string) bool { return true })
2937− assert.NoError(t, err)
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")
2944− rw := httptest.NewRecorder()
2945− proxy.ServeHTTP(rw, req)
2947− assert.Equal(t, 401, rw.Code)
2950func TestAllowedRequestNegateWithoutMethod(t *testing.T) {
2736func TestAllowedRequestNegateWithoutMethod(t *testing.T) {
2951 upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2737 upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2952 w.WriteHeader(200)
2738 w.WriteHeader(200)
@@ -2986,37 +2772,37 @@ func TestAllowedRequestNegateWithoutMethod(t *testing.T) {
2988 name: "Some static file allowed",
2774 name: "Some static file allowed",
2989− method: http.MethodGet,
2775+ method: "GET",
2990 url: "/static/file.txt",
2776 url: "/static/file.txt",
2991 allowed: true,
2777 allowed: true,
2994 name: "POST to contact form allowed",
2780 name: "POST to contact form allowed",
2995− method: http.MethodPost,
2781+ method: "POST",
2996 url: "/contact",
2782 url: "/contact",
2997 allowed: true,
2783 allowed: true,
3000 name: "Regex POST allowed",
2786 name: "Regex POST allowed",
3001− method: http.MethodPost,
2787+ method: "POST",
3002 url: "/api/public-entity",
2788 url: "/api/public-entity",
3003 allowed: true,
2789 allowed: true,
3006 name: "Regex POST with trailing slash allowed",
2792 name: "Regex POST with trailing slash allowed",
3007− method: http.MethodPost,
2793+ method: "POST",
3008 url: "/api/public-entity/",
2794 url: "/api/public-entity/",
3009 allowed: true,
2795 allowed: true,
3012 name: "Regex GET api route denied",
2798 name: "Regex GET api route denied",
3013− method: http.MethodGet,
2799+ method: "GET",
3014 url: "/api/users",
2800 url: "/api/users",
3015 allowed: false,
2801 allowed: false,
3018 name: "Regex POST api route denied",
2804 name: "Regex POST api route denied",
3019− method: http.MethodPost,
2805+ method: "POST",
3020 url: "/api/users",
2806 url: "/api/users",
3021 allowed: false,
2807 allowed: false,
@@ -3086,37 +2872,37 @@ func TestAllowedRequestNegateWithMethod(t *testing.T) {
3088 name: "Some static file allowed",
2874 name: "Some static file allowed",
3089− method: http.MethodGet,
2875+ method: "GET",
3090 url: "/static/file.txt",
2876 url: "/static/file.txt",
3091 allowed: true,
2877 allowed: true,
3094 name: "POST to contact form not allowed",
2880 name: "POST to contact form not allowed",
3095− method: http.MethodPost,
2881+ method: "POST",
3096 url: "/contact",
2882 url: "/contact",
3097 allowed: false,
2883 allowed: false,
3100 name: "Regex POST allowed",
2886 name: "Regex POST allowed",
3101− method: http.MethodPost,
2887+ method: "POST",
3102 url: "/api/public-entity",
2888 url: "/api/public-entity",
3103 allowed: true,
2889 allowed: true,
3106 name: "Regex POST with trailing slash allowed",
2892 name: "Regex POST with trailing slash allowed",
3107− method: http.MethodPost,
2893+ method: "POST",
3108 url: "/api/public-entity/",
2894 url: "/api/public-entity/",
3109 allowed: true,
2895 allowed: true,
3112 name: "Regex GET api route denied",
2898 name: "Regex GET api route denied",
3113− method: http.MethodGet,
2899+ method: "GET",
3114 url: "/api/users",
2900 url: "/api/users",
3115 allowed: false,
2901 allowed: false,
3118 name: "Regex POST api route denied",
2904 name: "Regex POST api route denied",
3119− method: http.MethodPost,
2905+ method: "POST",
3120 url: "/api/users",
2906 url: "/api/users",
3121 allowed: false,
2907 allowed: false,
@@ -3152,75 +2938,12 @@ func TestProxyAllowedGroups(t *testing.T) {
3152 name string
2938 name string
3153 allowedGroups []string
2939 allowedGroups []string
3154 groups []string
2940 groups []string
3156 expectUnauthorized bool
2941 expectUnauthorized bool
3159− name: "NoAllowedGroups",
2943+ {"NoAllowedGroups", []string{}, []string{}, false},
3160− allowedGroups: []string{},
3161− groups: []string{},
3163− expectUnauthorized: false},
3165− name: "NoAllowedGroupsUserHasGroups",
2944+ {"NoAllowedGroupsUserHasGroups", []string{}, []string{"a", "b"}, false},
3166− allowedGroups: []string{},
3167− groups: []string{"a", "b"},
3169− expectUnauthorized: false},
3171− name: "UserInAllowedGroup",
2945+ {"UserInAllowedGroup", []string{"a"}, []string{"a", "b"}, false},
3172− allowedGroups: []string{"a"},
3173− groups: []string{"a", "b"},
3175− expectUnauthorized: false},
3177− name: "UserNotInAllowedGroup",
2946+ {"UserNotInAllowedGroup", []string{"a"}, []string{"c"}, true},
3178− allowedGroups: []string{"a"},
3179− groups: []string{"c"},
3181− expectUnauthorized: true},
3183− name: "UserInQuerystringGroup",
3184− allowedGroups: []string{"a", "b"},
3185− groups: []string{"a", "c"},
3186− querystring: "?allowed_groups=a",
3187− expectUnauthorized: false},
3189− name: "UserInMultiParamQuerystringGroup",
3190− allowedGroups: []string{"a", "b"},
3191− groups: []string{"b"},
3192− querystring: "?allowed_groups=a&allowed_groups=b,d",
3193− expectUnauthorized: false},
3195− name: "UserInOnlyQuerystringGroup",
3196− allowedGroups: []string{},
3197− groups: []string{"a", "c"},
3198− querystring: "?allowed_groups=a,b",
3199− expectUnauthorized: false},
3201− name: "UserInDelimitedQuerystringGroup",
3202− allowedGroups: []string{"a", "b", "c"},
3203− groups: []string{"c"},
3204− querystring: "?allowed_groups=a,c",
3205− expectUnauthorized: false},
3207− name: "UserNotInQuerystringGroup",
3208− allowedGroups: []string{},
3209− groups: []string{"c"},
3210− querystring: "?allowed_groups=a,b",
3211− expectUnauthorized: true},
3213− name: "UserInConfigGroupNotInQuerystringGroup",
3214− allowedGroups: []string{"a", "b", "c"},
3215− groups: []string{"c"},
3216− querystring: "?allowed_groups=a,b",
3217− expectUnauthorized: true},
3219− name: "UserInQuerystringGroupNotInConfigGroup",
3220− allowedGroups: []string{"a", "b"},
3221− groups: []string{"c"},
3222− querystring: "?allowed_groups=b,c",
3223− expectUnauthorized: true},
3226 for _, tt := range tests {
2949 for _, tt := range tests {
@@ -3256,7 +2979,7 @@ func TestProxyAllowedGroups(t *testing.T) {
3256 t.Fatal(err)
2979 t.Fatal(err)
3259− test.req, _ = http.NewRequest(http.MethodGet, fmt.Sprintf("/%s", tt.querystring), nil)
2982+ test.req, _ = http.NewRequest("GET", "/", nil)
3261 test.req.Header.Add("accept", applicationJSON)
2984 test.req.Header.Add("accept", applicationJSON)
3262 err = test.SaveSession(session)
2985 err = test.SaveSession(session)
@@ -3400,7 +3123,7 @@ func TestAuthOnlyAllowedGroupsWithSkipMethods(t *testing.T) {
3401 name: "UserWithGroupSkipAuthPreflight",
3124 name: "UserWithGroupSkipAuthPreflight",
3402 groups: []string{"a", "c"},
3125 groups: []string{"a", "c"},
3403− method: http.MethodOptions,
3126+ method: "OPTIONS",
3404 ip: "1.2.3.5:43670",
3127 ip: "1.2.3.5:43670",
3405 withSession: true,
3128 withSession: true,
3406 expectedStatusCode: http.StatusAccepted,
3129 expectedStatusCode: http.StatusAccepted,
@@ -3408,7 +3131,7 @@ func TestAuthOnlyAllowedGroupsWithSkipMethods(t *testing.T) {
3409 name: "UserWithGroupTrustedIp",
3132 name: "UserWithGroupTrustedIp",
3410 groups: []string{"a", "c"},
3133 groups: []string{"a", "c"},
3411− method: http.MethodGet,
3134+ method: "GET",
3412 ip: "1.2.3.4:43670",
3135 ip: "1.2.3.4:43670",
3413 withSession: true,
3136 withSession: true,
3414 expectedStatusCode: http.StatusAccepted,
3137 expectedStatusCode: http.StatusAccepted,
@@ -3416,7 +3139,7 @@ func TestAuthOnlyAllowedGroupsWithSkipMethods(t *testing.T) {
3417 name: "UserWithoutGroupSkipAuthPreflight",
3140 name: "UserWithoutGroupSkipAuthPreflight",
3418 groups: []string{"c"},
3141 groups: []string{"c"},
3419− method: http.MethodOptions,
3142+ method: "OPTIONS",
3420 ip: "1.2.3.5:43670",
3143 ip: "1.2.3.5:43670",
3421 withSession: true,
3144 withSession: true,
3422 expectedStatusCode: http.StatusForbidden,
3145 expectedStatusCode: http.StatusForbidden,
@@ -3424,21 +3147,21 @@ func TestAuthOnlyAllowedGroupsWithSkipMethods(t *testing.T) {
3425 name: "UserWithoutGroupTrustedIp",
3148 name: "UserWithoutGroupTrustedIp",
3426 groups: []string{"c"},
3149 groups: []string{"c"},
3427− method: http.MethodGet,
3150+ method: "GET",
3428 ip: "1.2.3.4:43670",
3151 ip: "1.2.3.4:43670",
3429 withSession: true,
3152 withSession: true,
3430 expectedStatusCode: http.StatusForbidden,
3153 expectedStatusCode: http.StatusForbidden,
3433 name: "UserWithoutSessionSkipAuthPreflight",
3156 name: "UserWithoutSessionSkipAuthPreflight",
3434− method: http.MethodOptions,
3157+ method: "OPTIONS",
3435 ip: "1.2.3.5:43670",
3158 ip: "1.2.3.5:43670",
3436 withSession: false,
3159 withSession: false,
3437 expectedStatusCode: http.StatusAccepted,
3160 expectedStatusCode: http.StatusAccepted,
3440 name: "UserWithoutSessionTrustedIp",
3163 name: "UserWithoutSessionTrustedIp",
3441− method: http.MethodGet,
3164+ method: "GET",
3442 ip: "1.2.3.4:43670",
3165 ip: "1.2.3.4:43670",
3443 withSession: false,
3166 withSession: false,
3444 expectedStatusCode: http.StatusAccepted,
3167 expectedStatusCode: http.StatusAccepted,
@@ -3538,24 +3261,6 @@ func TestAuthOnlyAllowedEmailDomains(t *testing.T) {
3538 querystring: "?allowed_email_domains=a.b.c.example.com,*.c.example.com",
3261 querystring: "?allowed_email_domains=a.b.c.example.com,*.c.example.com",
3539 expectedStatusCode: http.StatusAccepted,
3262 expectedStatusCode: http.StatusAccepted,
3542− name: "UserWithMultipleAtSignsExactDomain",
3543− email: "attacker@evil.com@example.com",
3544− querystring: "?allowed_email_domains=example.com",
3545− expectedStatusCode: http.StatusForbidden,
3548− name: "UserWithMultipleAtSignsWildcardDomain",
3549− email: "attacker@evil.com@foo.example.com",
3550− querystring: "?allowed_email_domains=*.example.com",
3551− expectedStatusCode: http.StatusForbidden,
3554− name: "UserWithMultipleAtSignsDotPrefixedDomain",
3555− email: "attacker@evil.com@foo.example.com",
3556− querystring: "?allowed_email_domains=.example.com",
3557− expectedStatusCode: http.StatusForbidden,
3561 for _, tc := range testCases {
3266 for _, tc := range testCases {
@@ -3762,49 +3467,3 @@ func TestGetOAuthRedirectURI(t *testing.T) {
3766−func TestIdTokenPlaceholderInSignOut(t *testing.T) {
3767− opts := baseTestOptions()
3768− opts.WhitelistDomains = []string{"my-oidc-provider.example.com"}
3770− err := validation.Validate(opts)
3771− assert.NoError(t, err)
3773− const emailAddress = "john.doe@example.com"
3774− const userName = "9fcab5c9b889a557"
3775− created := time.Now()
3777− session := &sessions.SessionState{
3779− Groups: []string{"a", "b"},
3780− Email: emailAddress,
3781− IDToken: "eYjjjjjj.vvvv.ddd",
3782− AccessToken: "oauth_token",
3783− CreatedAt: &created,
3786− proxy, err := NewOAuthProxy(opts, func(email string) bool {
3789− assert.NoError(t, err)
3791− // Save the required session
3792− rw := httptest.NewRecorder()
3793− req, _ := http.NewRequest(http.MethodGet, "/", nil)
3794− err = proxy.sessionStore.Save(rw, req, session)
3795− assert.NoError(t, err)
3797− rw = httptest.NewRecorder()
3799− 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/")
3800− req, _ = http.NewRequest(http.MethodGet, "/oauth2/sign_out?rd="+rdUrl, nil)
3801− req = middlewareapi.AddRequestScope(req, &middlewareapi.RequestScope{
3802− RequestID: "11111111-2222-4333-8444-555555555555",
3806− proxy.SignOut(rw, req)
3807− newLocation := rw.Header().Values("Location")[0]
3809− assert.Equal(t, "https://my-oidc-provider.example.com/sign_out_page?id_token_hint=eYjjjjjj.vvvv.ddd&post_logout_redirect_uri=https://my-app.example.com/", newLocation)