git.iko.soy/typeable/oauth2-proxy
on master help sign in
Improve the Nginx `auth_request` example (#2278)

* The `X-Forwarded-Uri` was required to bypass authentication - Fix the `skip_auth_routes` option not working in Nginx * Add tests for allowed requests with proxied `X-Forwarded-Uri` header * Avoid nginx startup failure: host not found in upstream "oauth2-proxy" * The `--reverse-proxy` option is required for nginx * Update the change logs * Use the authOnlyPath constant * Remove the unused header `X-Scheme`

commit5e8956b52f49a0ca11fc54c95c8c033ee9ca71cf authorCharley Wu <akunzai@gmail.com> dateFri 3 Nov 2023, 06:57 (3 years ago) parent66bfd8e
7 files changed+107−3
CHANGELOG.md+1 contrib/local-environment/docker-compose-nginx.yaml+1 contrib/local-environment/nginx.conf+2 contrib/local-environment/oauth2-proxy-nginx.cfg+2 docs/docs/configuration/overview.md+3−2 docs/docs/configuration/tls.md−1 oauthproxy_test.go+98
CHANGELOG.md+1
@@ -13,6 +13,7 @@
1313- [#2237](https://github.com/oauth2-proxy/oauth2-proxy/pull/2237) adds an option to append CA certificates (@emsixteeen)
1414- [#2128](https://github.com/oauth2-proxy/oauth2-proxy/pull/2128) Update dependencies (@vllvll)
1515- [#2274](https://github.com/oauth2-proxy/oauth2-proxy/pull/2274) Upgrade golang.org/x/net to v0.17.0 (@pierluigilenoci)
16+- [#2278](https://github.com/oauth2-proxy/oauth2-proxy/pull/2278) Improve the Nginx auth_request example (@akunzai)
1617- [#2282](https://github.com/oauth2-proxy/oauth2-proxy/pull/2282) Fixed checking Google Groups membership using Google Application Credentials (@kvanzuijlen)
1718- [#2183](https://github.com/oauth2-proxy/oauth2-proxy/pull/2183) Allowing relative redirect url though an option
1819- [#1866](https://github.com/oauth2-proxy/oauth2-proxy/pull/1866) Add support for unix socker as upstream (@babs)
contrib/local-environment/docker-compose-nginx.yaml+1
@@ -31,6 +31,7 @@ services:
3131 nginx:
3232 container_name: nginx
3333 image: nginx:1.18
34+ restart: unless-stopped
3435 ports:
3536 - 80:80/tcp
3637 hostname: nginx
contrib/local-environment/nginx.conf+2
@@ -38,6 +38,7 @@ server {
3838 # Make sure the OAuth2 Proxy knows where the original request came from.
3939 proxy_set_header Host $host;
4040 proxy_set_header X-Real-IP $remote_addr;
41+ proxy_set_header X-Forwarded-Uri $request_uri;
4142
4243 proxy_pass http://oauth2-proxy:4180/;
4344 }
@@ -78,6 +79,7 @@ server {
7879 # Make sure the OAuth2 Proxy knows where the original request came from.
7980 proxy_set_header Host $host;
8081 proxy_set_header X-Real-IP $remote_addr;
82+ proxy_set_header X-Forwarded-Uri $request_uri;
8183
8284 proxy_pass http://oauth2-proxy:4180/;
8385 }
contrib/local-environment/oauth2-proxy-nginx.cfg+2
@@ -10,3 +10,5 @@ cookie_secure="false"
1010redirect_url="http://oauth2-proxy.oauth2-proxy.localhost/oauth2/callback"
1111cookie_domains=".oauth2-proxy.localhost" # Required so cookie can be read on all subdomains.
1212whitelist_domains=".oauth2-proxy.localhost" # Required to allow redirection back to original requested target.
13+# Enables the use of `X-Forwarded-*` headers to determine request correctly
14+reverse_proxy="true"
docs/docs/configuration/overview.md+3−2
@@ -339,6 +339,8 @@ Available variables for standard logging:
339339
340340## Configuring for use with the Nginx `auth_request` directive
341341
342+**This option requires `--reverse-proxy` option to be set.**
343+
342344The [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:
343345
344346```nginx
@@ -351,7 +353,6 @@ server {
351353 proxy_pass http://127.0.0.1:4180;
352354 proxy_set_header Host $host;
353355 proxy_set_header X-Real-IP $remote_addr;
354− proxy_set_header X-Scheme $scheme;
355356 proxy_set_header X-Auth-Request-Redirect $request_uri;
356357 # or, if you are handling multiple domains:
357358 # proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
@@ -360,7 +361,7 @@ server {
360361 proxy_pass http://127.0.0.1:4180;
361362 proxy_set_header Host $host;
362363 proxy_set_header X-Real-IP $remote_addr;
363− proxy_set_header X-Scheme $scheme;
364+ proxy_set_header X-Forwarded-Uri $request_uri;
364365 # nginx auth_request includes headers but not body
365366 proxy_set_header Content-Length "";
366367 proxy_pass_request_body off;
docs/docs/configuration/tls.md−1
@@ -63,7 +63,6 @@ There are two recommended configurations:
6363 proxy_pass http://127.0.0.1:4180;
6464 proxy_set_header Host $host;
6565 proxy_set_header X-Real-IP $remote_addr;
66− proxy_set_header X-Scheme $scheme;
6766 proxy_connect_timeout 1;
6867 proxy_send_timeout 30;
6968 proxy_read_timeout 30;
oauthproxy_test.go+98
@@ -2632,6 +2632,104 @@ func TestAllowedRequest(t *testing.T) {
26322632 }
26332633}
26342634
2635+func TestAllowedRequestWithForwardedUriHeader(t *testing.T) {
2636+ upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2637+ w.WriteHeader(200)
2638+ }))
2639+ t.Cleanup(upstreamServer.Close)
2640+
2641+ opts := baseTestOptions()
2642+ opts.ReverseProxy = true
2643+ opts.UpstreamServers = options.UpstreamConfig{
2644+ Upstreams: []options.Upstream{
2645+ {
2646+ ID: upstreamServer.URL,
2647+ Path: "/",
2648+ URI: upstreamServer.URL,
2649+ },
2650+ },
2651+ }
2652+ opts.SkipAuthRegex = []string{
2653+ "^/skip/auth/regex$",
2654+ }
2655+ opts.SkipAuthRoutes = []string{
2656+ "GET=^/skip/auth/routes/get",
2657+ }
2658+ err := validation.Validate(opts)
2659+ assert.NoError(t, err)
2660+ proxy, err := NewOAuthProxy(opts, func(_ string) bool { return true })
2661+ if err != nil {
2662+ t.Fatal(err)
2663+ }
2664+
2665+ testCases := []struct {
2666+ name string
2667+ method string
2668+ url string
2669+ allowed bool
2670+ }{
2671+ {
2672+ name: "Regex GET allowed",
2673+ method: "GET",
2674+ url: "/skip/auth/regex",
2675+ allowed: true,
2676+ },
2677+ {
2678+ name: "Regex POST allowed ",
2679+ method: "POST",
2680+ url: "/skip/auth/regex",
2681+ allowed: true,
2682+ },
2683+ {
2684+ name: "Regex denied",
2685+ method: "GET",
2686+ url: "/wrong/denied",
2687+ allowed: false,
2688+ },
2689+ {
2690+ name: "Route allowed",
2691+ method: "GET",
2692+ url: "/skip/auth/routes/get",
2693+ allowed: true,
2694+ },
2695+ {
2696+ name: "Route denied with wrong method",
2697+ method: "PATCH",
2698+ url: "/skip/auth/routes/get",
2699+ allowed: false,
2700+ },
2701+ {
2702+ name: "Route denied with wrong path",
2703+ method: "GET",
2704+ url: "/skip/auth/routes/wrong/path",
2705+ allowed: false,
2706+ },
2707+ {
2708+ name: "Route denied with wrong path and method",
2709+ method: "POST",
2710+ url: "/skip/auth/routes/wrong/path",
2711+ allowed: false,
2712+ },
2713+ }
2714+
2715+ for _, tc := range testCases {
2716+ t.Run(tc.name, func(t *testing.T) {
2717+ req, err := http.NewRequest(tc.method, opts.ProxyPrefix+authOnlyPath, nil)
2718+ req.Header.Set("X-Forwarded-Uri", tc.url)
2719+ assert.NoError(t, err)
2720+
2721+ rw := httptest.NewRecorder()
2722+ proxy.ServeHTTP(rw, req)
2723+
2724+ if tc.allowed {
2725+ assert.Equal(t, 202, rw.Code)
2726+ } else {
2727+ assert.Equal(t, 401, rw.Code)
2728+ }
2729+ })
2730+ }
2731+}
2732+
26352733func TestAllowedRequestNegateWithoutMethod(t *testing.T) {
26362734 upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
26372735 w.WriteHeader(200)