@@ -1,7 +1,6 @@
1package main
1package main
7 "encoding/base64"
6 "encoding/base64"
@@ -11,7 +10,6 @@ import (
11 "net/http"
10 "net/http"
12 "net/http/httptest"
11 "net/http/httptest"
@@ -19,7 +17,6 @@ import (
20 "github.com/coreos/go-oidc"
18 "github.com/coreos/go-oidc"
21 "github.com/mbland/hmacauth"
19 "github.com/mbland/hmacauth"
22− "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
23 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
20 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
24 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
21 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
25 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/cookies"
22 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/cookies"
@@ -28,10 +25,7 @@ import (
28 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/upstream"
25 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/upstream"
29 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/validation"
26 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/validation"
30 "github.com/oauth2-proxy/oauth2-proxy/v7/providers"
27 "github.com/oauth2-proxy/oauth2-proxy/v7/providers"
31− . "github.com/onsi/ginkgo"
32− . "github.com/onsi/gomega"
33 "github.com/stretchr/testify/assert"
28 "github.com/stretchr/testify/assert"
34− "github.com/stretchr/testify/require"
@@ -63,304 +57,6 @@ func TestRobotsTxt(t *testing.T) {
63 assert.Equal(t, "User-agent: *\nDisallow: /\n", rw.Body.String())
57 assert.Equal(t, "User-agent: *\nDisallow: /\n", rw.Body.String())
66−func TestIsValidRedirect(t *testing.T) {
67− opts := baseTestOptions()
68− // Should match domains that are exactly foo.bar and any subdomain of bar.foo
69− opts.WhitelistDomains = []string{
73− ".sub.port.bar:8080",
75− ".sub.anyport.bar:*",
77− err := validation.Validate(opts)
78− assert.NoError(t, err)
80− proxy, err := NewOAuthProxy(opts, func(string) bool { return true })
85− testCases := []struct {
86− Desc, Redirect string
92− ExpectedResult: false,
96− Redirect: "/redirect",
97− ExpectedResult: true,
100− Desc: "doubleSlash",
101− Redirect: "//redirect",
102− ExpectedResult: false,
106− Redirect: "http://foo.bar/redirect",
107− ExpectedResult: true,
111− Redirect: "https://foo.bar/redirect",
112− ExpectedResult: true,
115− Desc: "invalidHTTPSubdomain",
116− Redirect: "http://baz.foo.bar/redirect",
117− ExpectedResult: false,
120− Desc: "invalidHTTPSSubdomain",
121− Redirect: "https://baz.foo.bar/redirect",
122− ExpectedResult: false,
125− Desc: "validHTTPSubdomain",
126− Redirect: "http://baz.bar.foo/redirect",
127− ExpectedResult: true,
130− Desc: "validHTTPSSubdomain",
131− Redirect: "https://baz.bar.foo/redirect",
132− ExpectedResult: true,
135− Desc: "validHTTPDomain",
136− Redirect: "http://bar.foo/redirect",
137− ExpectedResult: true,
140− Desc: "invalidHTTP1",
141− Redirect: "http://foo.bar.evil.corp/redirect",
142− ExpectedResult: false,
145− Desc: "invalidHTTPS1",
146− Redirect: "https://foo.bar.evil.corp/redirect",
147− ExpectedResult: false,
150− Desc: "invalidHTTP2",
151− Redirect: "http://evil.corp/redirect?rd=foo.bar",
152− ExpectedResult: false,
155− Desc: "invalidHTTPS2",
156− Redirect: "https://evil.corp/redirect?rd=foo.bar",
157− ExpectedResult: false,
160− Desc: "invalidPort",
161− Redirect: "https://evil.corp:3838/redirect",
162− ExpectedResult: false,
165− Desc: "invalidEmptyPort",
166− Redirect: "http://foo.bar:3838/redirect",
167− ExpectedResult: false,
170− Desc: "invalidEmptyPortSubdomain",
171− Redirect: "http://baz.bar.foo:3838/redirect",
172− ExpectedResult: false,
175− Desc: "validSpecificPort",
176− Redirect: "http://port.bar:8080/redirect",
177− ExpectedResult: true,
180− Desc: "invalidSpecificPort",
181− Redirect: "http://port.bar:3838/redirect",
182− ExpectedResult: false,
185− Desc: "validSpecificPortSubdomain",
186− Redirect: "http://foo.sub.port.bar:8080/redirect",
187− ExpectedResult: true,
190− Desc: "invalidSpecificPortSubdomain",
191− Redirect: "http://foo.sub.port.bar:3838/redirect",
192− ExpectedResult: false,
195− Desc: "validAnyPort1",
196− Redirect: "http://anyport.bar:8080/redirect",
197− ExpectedResult: true,
200− Desc: "validAnyPort2",
201− Redirect: "http://anyport.bar:8081/redirect",
202− ExpectedResult: true,
205− Desc: "validAnyPortSubdomain1",
206− Redirect: "http://a.sub.anyport.bar:8080/redirect",
207− ExpectedResult: true,
210− Desc: "validAnyPortSubdomain2",
211− Redirect: "http://a.sub.anyport.bar:8081/redirect",
212− ExpectedResult: true,
215− Desc: "openRedirect1",
216− Redirect: "/\\evil.com",
217− ExpectedResult: false,
220− Desc: "openRedirectSpace1",
221− Redirect: "/ /evil.com",
222− ExpectedResult: false,
225− Desc: "openRedirectSpace2",
226− Redirect: "/ \\evil.com",
227− ExpectedResult: false,
230− Desc: "openRedirectTab1",
231− Redirect: "/\t/evil.com",
232− ExpectedResult: false,
235− Desc: "openRedirectTab2",
236− Redirect: "/\t\\evil.com",
237− ExpectedResult: false,
240− Desc: "openRedirectVerticalTab1",
241− Redirect: "/\v/evil.com",
242− ExpectedResult: false,
245− Desc: "openRedirectVerticalTab2",
246− Redirect: "/\v\\evil.com",
247− ExpectedResult: false,
250− Desc: "openRedirectNewLine1",
251− Redirect: "/\n/evil.com",
252− ExpectedResult: false,
255− Desc: "openRedirectNewLine2",
256− Redirect: "/\n\\evil.com",
257− ExpectedResult: false,
260− Desc: "openRedirectCarriageReturn1",
261− Redirect: "/\r/evil.com",
262− ExpectedResult: false,
265− Desc: "openRedirectCarriageReturn2",
266− Redirect: "/\r\\evil.com",
267− ExpectedResult: false,
270− Desc: "openRedirectTripleTab",
271− Redirect: "/\t\t/\t/evil.com",
272− ExpectedResult: false,
275− Desc: "openRedirectTripleTab2",
276− Redirect: "/\t\t\\\t/evil.com",
277− ExpectedResult: false,
280− Desc: "openRedirectQuadTab1",
281− Redirect: "/\t\t/\t\t\\evil.com",
282− ExpectedResult: false,
285− Desc: "openRedirectQuadTab2",
286− Redirect: "/\t\t\\\t\t/evil.com",
287− ExpectedResult: false,
290− Desc: "openRedirectPeriod1",
291− Redirect: "/./\\evil.com",
292− ExpectedResult: false,
295− Desc: "openRedirectPeriod2",
296− Redirect: "/./../../\\evil.com",
297− ExpectedResult: false,
300− Desc: "openRedirectDoubleTab",
301− Redirect: "/\t/\t\\evil.com",
302− ExpectedResult: false,
305− Desc: "openRedirectPartialSubdomain",
306− Redirect: "http://evilbar.foo",
307− ExpectedResult: false,
311− for _, tc := range testCases {
312− t.Run(tc.Desc, func(t *testing.T) {
313− result := proxy.IsValidRedirect(tc.Redirect)
315− if result != tc.ExpectedResult {
316− t.Errorf("expected %t got %t", tc.ExpectedResult, result)
322−var _ = Describe("OpenRedirect Tests", func() {
323− var proxy *OAuthProxy
326− opts := baseTestOptions()
327− // Should match domains that are exactly foo.bar and any subdomain of bar.foo
328− opts.WhitelistDomains = []string{
332− ".sub.port.bar:8080",
334− ".sub.anyport.bar:*",
335− "www.whitelisteddomain.tld",
337− Expect(validation.Validate(opts)).To(Succeed())
340− proxy, err = NewOAuthProxy(opts, func(string) bool { return true })
341− Expect(err).ToNot(HaveOccurred())
344− file, err := os.Open("./testdata/openredirects.txt")
345− Expect(err).ToNot(HaveOccurred())
347− Expect(file.Close()).To(Succeed())
350− scanner := bufio.NewScanner(file)
351− for scanner.Scan() {
352− rd := scanner.Text()
354− rdUnescaped, err := url.QueryUnescape(rd)
355− Expect(err).ToNot(HaveOccurred())
357− Expect(proxy.IsValidRedirect(rdUnescaped)).To(BeFalse(), "Expected redirect not to be valid")
361− Expect(scanner.Err()).ToNot(HaveOccurred())
364type TestProvider struct {
60type TestProvider struct {
365 *providers.ProviderData
61 *providers.ProviderData
366 EmailAddress string
62 EmailAddress string
@@ -1770,165 +1466,6 @@ func TestRequestSignature(t *testing.T) {
1773−func Test_getAppRedirect(t *testing.T) {
1774− opts := baseTestOptions()
1775− opts.WhitelistDomains = append(opts.WhitelistDomains, ".example.com", ".example.com:8443")
1776− err := validation.Validate(opts)
1777− assert.NoError(t, err)
1778− require.NotEmpty(t, opts.ProxyPrefix)
1779− proxy, err := NewOAuthProxy(opts, func(s string) bool { return false })
1784− tests := []struct {
1787− headers map[string]string
1789− expectedRedirect string
1792− name: "request outside of ProxyPrefix redirects to original URL",
1795− reverseProxy: false,
1796− expectedRedirect: "/foo/bar",
1799− name: "request with query preserves query",
1802− reverseProxy: false,
1803− expectedRedirect: "/foo?bar",
1806− name: "request under ProxyPrefix redirects to root",
1807− url: proxy.ProxyPrefix + "/foo/bar",
1809− reverseProxy: false,
1810− expectedRedirect: "/",
1813− name: "proxied request outside of ProxyPrefix redirects to proxied URL",
1814− url: "https://oauth.example.com/foo/bar",
1815− headers: map[string]string{
1816− "X-Forwarded-Proto": "https",
1817− "X-Forwarded-Host": "a-service.example.com",
1818− "X-Forwarded-Uri": "/foo/bar",
1820− reverseProxy: true,
1821− expectedRedirect: "https://a-service.example.com/foo/bar",
1824− name: "non-proxied request with spoofed proxy headers wouldn't redirect",
1825− url: "https://oauth.example.com/foo?bar",
1826− headers: map[string]string{
1827− "X-Forwarded-Proto": "https",
1828− "X-Forwarded-Host": "a-service.example.com",
1829− "X-Forwarded-Uri": "/foo/bar",
1831− reverseProxy: false,
1832− expectedRedirect: "/foo?bar",
1835− name: "proxied request under ProxyPrefix redirects to root",
1836− url: "https://oauth.example.com" + proxy.ProxyPrefix + "/foo/bar",
1837− headers: map[string]string{
1838− "X-Forwarded-Proto": "https",
1839− "X-Forwarded-Host": "a-service.example.com",
1840− "X-Forwarded-Uri": proxy.ProxyPrefix + "/foo/bar",
1842− reverseProxy: true,
1843− expectedRedirect: "https://a-service.example.com/",
1846− name: "proxied request with port under ProxyPrefix redirects to root",
1847− url: "https://oauth.example.com" + proxy.ProxyPrefix + "/foo/bar",
1848− headers: map[string]string{
1849− "X-Forwarded-Proto": "https",
1850− "X-Forwarded-Host": "a-service.example.com:8443",
1851− "X-Forwarded-Uri": proxy.ProxyPrefix + "/foo/bar",
1853− reverseProxy: true,
1854− expectedRedirect: "https://a-service.example.com:8443/",
1857− name: "proxied request with missing uri header would still redirect to desired redirect",
1858− url: "https://oauth.example.com/foo?bar",
1859− headers: map[string]string{
1860− "X-Forwarded-Proto": "https",
1861− "X-Forwarded-Host": "a-service.example.com",
1863− reverseProxy: true,
1864− expectedRedirect: "https://a-service.example.com/foo?bar",
1867− name: "request with headers proxy not being set (and reverse proxy enabled) would still redirect to desired redirect",
1868− url: "https://oauth.example.com/foo?bar",
1870− reverseProxy: true,
1871− expectedRedirect: "/foo?bar",
1874− name: "proxied request with X-Auth-Request-Redirect being set outside of ProxyPrefix redirects to proxied URL",
1875− url: "https://oauth.example.com/foo/bar",
1876− headers: map[string]string{
1877− "X-Auth-Request-Redirect": "https://a-service.example.com/foo/bar",
1879− reverseProxy: true,
1880− expectedRedirect: "https://a-service.example.com/foo/bar",
1883− name: "proxied request with rd query string redirects to proxied URL",
1884− url: "https://oauth.example.com/foo/bar?rd=https%3A%2F%2Fa%2Dservice%2Eexample%2Ecom%2Ffoo%2Fbar",
1886− reverseProxy: false,
1887− expectedRedirect: "https://a-service.example.com/foo/bar",
1890− name: "proxied request with rd query string and all headers set (and reverse proxy not enabled) redirects to proxied URL on rd query string",
1891− url: "https://oauth.example.com/foo/bar?rd=https%3A%2F%2Fa%2Dservice%2Eexample%2Ecom%2Ffoo%2Fjazz",
1892− headers: map[string]string{
1893− "X-Auth-Request-Redirect": "https://a-service.example.com/foo/baz",
1894− "X-Forwarded-Proto": "http",
1895− "X-Forwarded-Host": "another-service.example.com",
1896− "X-Forwarded-Uri": "/seasons/greetings",
1898− reverseProxy: false,
1899− expectedRedirect: "https://a-service.example.com/foo/jazz",
1902− name: "proxied request with rd query string and some headers set redirects to proxied URL on rd query string",
1903− url: "https://oauth.example.com/foo/bar?rd=https%3A%2F%2Fa%2Dservice%2Eexample%2Ecom%2Ffoo%2Fbaz",
1904− headers: map[string]string{
1905− "X-Forwarded-Proto": "https",
1906− "X-Forwarded-Host": "another-service.example.com",
1907− "X-Forwarded-Uri": "/seasons/greetings",
1909− reverseProxy: true,
1910− expectedRedirect: "https://a-service.example.com/foo/baz",
1913− for _, tt := range tests {
1914− t.Run(tt.name, func(t *testing.T) {
1915− req, _ := http.NewRequest("GET", tt.url, nil)
1916− for header, value := range tt.headers {
1918− req.Header.Add(header, value)
1921− req = middleware.AddRequestScope(req, &middleware.RequestScope{
1922− ReverseProxy: tt.reverseProxy,
1924− redirect, err := proxy.getAppRedirect(req)
1926− assert.NoError(t, err)
1927− assert.Equal(t, tt.expectedRedirect, redirect)
1932type ajaxRequestTest struct {
1469type ajaxRequestTest struct {
1933 opts *options.Options
1470 opts *options.Options
1934 proxy *OAuthProxy
1471 proxy *OAuthProxy