diff --git a/CHANGELOG.md b/CHANGELOG.md index 52a4b97cdc..2d4b1a73b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - [#2237](https://github.com/oauth2-proxy/oauth2-proxy/pull/2237) adds an option to append CA certificates (@emsixteeen) - [#2128](https://github.com/oauth2-proxy/oauth2-proxy/pull/2128) Update dependencies (@vllvll) - [#2274](https://github.com/oauth2-proxy/oauth2-proxy/pull/2274) Upgrade golang.org/x/net to v0.17.0 (@pierluigilenoci) +- [#2278](https://github.com/oauth2-proxy/oauth2-proxy/pull/2278) Improve the Nginx auth_request example (@akunzai) - [#2282](https://github.com/oauth2-proxy/oauth2-proxy/pull/2282) Fixed checking Google Groups membership using Google Application Credentials (@kvanzuijlen) - [#2183](https://github.com/oauth2-proxy/oauth2-proxy/pull/2183) Allowing relative redirect url though an option - [#1866](https://github.com/oauth2-proxy/oauth2-proxy/pull/1866) Add support for unix socker as upstream (@babs) diff --git a/contrib/local-environment/docker-compose-nginx.yaml b/contrib/local-environment/docker-compose-nginx.yaml index af6c587b39..582cd720e3 100644 --- a/contrib/local-environment/docker-compose-nginx.yaml +++ b/contrib/local-environment/docker-compose-nginx.yaml @@ -31,6 +31,7 @@ services: nginx: container_name: nginx image: nginx:1.18 + restart: unless-stopped ports: - 80:80/tcp hostname: nginx diff --git a/contrib/local-environment/nginx.conf b/contrib/local-environment/nginx.conf index 877c213ea4..42fc06e3cb 100644 --- a/contrib/local-environment/nginx.conf +++ b/contrib/local-environment/nginx.conf @@ -38,6 +38,7 @@ server { # Make sure the OAuth2 Proxy knows where the original request came from. proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Uri $request_uri; proxy_pass http://oauth2-proxy:4180/; } @@ -78,6 +79,7 @@ server { # Make sure the OAuth2 Proxy knows where the original request came from. proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Uri $request_uri; proxy_pass http://oauth2-proxy:4180/; } diff --git a/contrib/local-environment/oauth2-proxy-nginx.cfg b/contrib/local-environment/oauth2-proxy-nginx.cfg index 2258cce004..c60c3ac2d7 100644 --- a/contrib/local-environment/oauth2-proxy-nginx.cfg +++ b/contrib/local-environment/oauth2-proxy-nginx.cfg @@ -10,3 +10,5 @@ cookie_secure="false" redirect_url="http://oauth2-proxy.oauth2-proxy.localhost/oauth2/callback" cookie_domains=".oauth2-proxy.localhost" # Required so cookie can be read on all subdomains. whitelist_domains=".oauth2-proxy.localhost" # Required to allow redirection back to original requested target. +# Enables the use of `X-Forwarded-*` headers to determine request correctly +reverse_proxy="true" diff --git a/docs/docs/configuration/overview.md b/docs/docs/configuration/overview.md index e451c485e7..11d2fc8ffc 100644 --- a/docs/docs/configuration/overview.md +++ b/docs/docs/configuration/overview.md @@ -339,6 +339,8 @@ Available variables for standard logging: ## Configuring for use with the Nginx `auth_request` directive +**This option requires `--reverse-proxy` option to be set.** + The [Nginx `auth_request` directive](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) allows Nginx to authenticate requests via the oauth2-proxy's `/auth` endpoint, which only returns a 202 Accepted response or a 401 Unauthorized response without proxying the request through. For example: ```nginx @@ -351,7 +353,6 @@ server { proxy_pass http://127.0.0.1:4180; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Scheme $scheme; proxy_set_header X-Auth-Request-Redirect $request_uri; # or, if you are handling multiple domains: # proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri; @@ -360,7 +361,7 @@ server { proxy_pass http://127.0.0.1:4180; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Scheme $scheme; + proxy_set_header X-Forwarded-Uri $request_uri; # nginx auth_request includes headers but not body proxy_set_header Content-Length ""; proxy_pass_request_body off; diff --git a/docs/docs/configuration/tls.md b/docs/docs/configuration/tls.md index 21aa6f3bcc..68344b22d5 100644 --- a/docs/docs/configuration/tls.md +++ b/docs/docs/configuration/tls.md @@ -63,7 +63,6 @@ There are two recommended configurations: proxy_pass http://127.0.0.1:4180; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Scheme $scheme; proxy_connect_timeout 1; proxy_send_timeout 30; proxy_read_timeout 30; diff --git a/oauthproxy_test.go b/oauthproxy_test.go index 42c5b3db8e..a27db6e217 100644 --- a/oauthproxy_test.go +++ b/oauthproxy_test.go @@ -2632,6 +2632,104 @@ func TestAllowedRequest(t *testing.T) { } } +func TestAllowedRequestWithForwardedUriHeader(t *testing.T) { + upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + })) + t.Cleanup(upstreamServer.Close) + + opts := baseTestOptions() + opts.ReverseProxy = true + opts.UpstreamServers = options.UpstreamConfig{ + Upstreams: []options.Upstream{ + { + ID: upstreamServer.URL, + Path: "/", + URI: upstreamServer.URL, + }, + }, + } + opts.SkipAuthRegex = []string{ + "^/skip/auth/regex$", + } + opts.SkipAuthRoutes = []string{ + "GET=^/skip/auth/routes/get", + } + err := validation.Validate(opts) + assert.NoError(t, err) + proxy, err := NewOAuthProxy(opts, func(_ string) bool { return true }) + if err != nil { + t.Fatal(err) + } + + testCases := []struct { + name string + method string + url string + allowed bool + }{ + { + name: "Regex GET allowed", + method: "GET", + url: "/skip/auth/regex", + allowed: true, + }, + { + name: "Regex POST allowed ", + method: "POST", + url: "/skip/auth/regex", + allowed: true, + }, + { + name: "Regex denied", + method: "GET", + url: "/wrong/denied", + allowed: false, + }, + { + name: "Route allowed", + method: "GET", + url: "/skip/auth/routes/get", + allowed: true, + }, + { + name: "Route denied with wrong method", + method: "PATCH", + url: "/skip/auth/routes/get", + allowed: false, + }, + { + name: "Route denied with wrong path", + method: "GET", + url: "/skip/auth/routes/wrong/path", + allowed: false, + }, + { + name: "Route denied with wrong path and method", + method: "POST", + url: "/skip/auth/routes/wrong/path", + allowed: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + req, err := http.NewRequest(tc.method, opts.ProxyPrefix+authOnlyPath, nil) + req.Header.Set("X-Forwarded-Uri", tc.url) + assert.NoError(t, err) + + rw := httptest.NewRecorder() + proxy.ServeHTTP(rw, req) + + if tc.allowed { + assert.Equal(t, 202, rw.Code) + } else { + assert.Equal(t, 401, rw.Code) + } + }) + } +} + func TestAllowedRequestNegateWithoutMethod(t *testing.T) { upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200)