diff --git a/docs/docs/configuration/integrations/nginx.md b/docs/docs/configuration/integrations/nginx.md
index ca6402a9..88d226b3 100644
--- a/docs/docs/configuration/integrations/nginx.md
+++ b/docs/docs/configuration/integrations/nginx.md
@@ -152,6 +152,14 @@ This ensures:
- ✅ API clients fail fast with appropriate HTTP status codes
- ✅ `/oauth2/auth` remains a pure boolean oracle (2xx/401)
+### CORS Preflight Requests and `--skip-auth-preflight`
+
+`--skip-auth-preflight` only applies when oauth2-proxy receives the original `OPTIONS` request directly, such as when it is running as a reverse proxy.
+
+When nginx is configured with `auth_request`, it checks the original request via a separate internal GET subrequest to `/oauth2/auth` instead of proxying the original `OPTIONS` request through oauth2-proxy. In this integration, `--skip-auth-preflight` does not bypass authentication for browser CORS preflight checks.
+
+If you need unauthenticated preflight handling with nginx or ingress-nginx, handle `OPTIONS` before `auth_request` runs, or let your ingress CORS configuration answer the preflight directly. If nginx answers the preflight itself, make sure it also returns the required CORS headers.
+
When you use ingress-nginx in Kubernetes, you can configure the same behavior with the following annotations on your Ingress resource:
```yaml
diff --git a/docs/docs/configuration/overview.md b/docs/docs/configuration/overview.md
index 965953fa..7cfd9f40 100644
--- a/docs/docs/configuration/overview.md
+++ b/docs/docs/configuration/overview.md
@@ -217,7 +217,7 @@ When `--reverse-proxy` is enabled, configure `--trusted-proxy-ip` to the IPs or
| flag: `--reverse-proxy`
toml: `reverse_proxy` | bool | are we running behind a reverse proxy, controls whether headers like X-Real-IP are accepted and allows X-Forwarded-\{Proto,Host,Uri\} headers to be used on redirect selection | false |
| flag: `--trusted-proxy-ip`
toml: `trusted_proxy_ips` | string \| list | list of IPs or CIDR ranges allowed to supply `X-Forwarded-*` headers when `--reverse-proxy` is enabled. If not set, OAuth2 Proxy preserves backwards compatibility by trusting all source IPs (`0.0.0.0/0`, `::/0`) and logs a warning at startup. Configure this to your reverse proxy addresses to prevent forwarded header spoofing. | `"0.0.0.0/0", "::/0"` |
| flag: `--signature-key`
toml: `signature_key` | string | GAP-Signature request signature key (algorithm:secretkey) | |
-| flag: `--skip-auth-preflight`
toml: `skip_auth_preflight` | bool | will skip authentication for OPTIONS requests | false |
+| flag: `--skip-auth-preflight`
toml: `skip_auth_preflight` | bool | will skip authentication for OPTIONS requests handled directly by oauth2-proxy; does not apply to nginx `auth_request`, which calls `/oauth2/auth` via a separate GET subrequest | false |
| flag: `--skip-auth-regex`
toml: `skip_auth_regex` | string \| list | (DEPRECATED for `--skip-auth-route`) bypass authentication for requests paths that match (may be given multiple times). Path matching is performed against the normalized path only; fragment identifiers (`#`) and their URL-encoded form (`%23`) are stripped before evaluation. | |
| flag: `--skip-auth-route`
toml: `skip_auth_routes` | string \| list | bypass authentication for requests that match the method & path. Format: method=path_regex OR method!=path_regex. For all methods: path_regex OR !=path_regex. Path matching is performed against the normalized path only; fragment identifiers (`#`) and their URL-encoded form (`%23`) are stripped before evaluation. | |
| flag: `--skip-jwt-bearer-tokens`
toml: `skip_jwt_bearer_tokens` | bool | will skip requests that have verified JWT bearer tokens (the token must have [`aud`](https://en.wikipedia.org/wiki/JSON_Web_Token#Standard_fields) that matches this client id or one of the extras from `extra-jwt-issuers`) | false |
diff --git a/docs/versioned_docs/version-7.15.x/configuration/integrations/nginx.md b/docs/versioned_docs/version-7.15.x/configuration/integrations/nginx.md
index ca6402a9..88d226b3 100644
--- a/docs/versioned_docs/version-7.15.x/configuration/integrations/nginx.md
+++ b/docs/versioned_docs/version-7.15.x/configuration/integrations/nginx.md
@@ -152,6 +152,14 @@ This ensures:
- ✅ API clients fail fast with appropriate HTTP status codes
- ✅ `/oauth2/auth` remains a pure boolean oracle (2xx/401)
+### CORS Preflight Requests and `--skip-auth-preflight`
+
+`--skip-auth-preflight` only applies when oauth2-proxy receives the original `OPTIONS` request directly, such as when it is running as a reverse proxy.
+
+When nginx is configured with `auth_request`, it checks the original request via a separate internal GET subrequest to `/oauth2/auth` instead of proxying the original `OPTIONS` request through oauth2-proxy. In this integration, `--skip-auth-preflight` does not bypass authentication for browser CORS preflight checks.
+
+If you need unauthenticated preflight handling with nginx or ingress-nginx, handle `OPTIONS` before `auth_request` runs, or let your ingress CORS configuration answer the preflight directly. If nginx answers the preflight itself, make sure it also returns the required CORS headers.
+
When you use ingress-nginx in Kubernetes, you can configure the same behavior with the following annotations on your Ingress resource:
```yaml
diff --git a/docs/versioned_docs/version-7.15.x/configuration/overview.md b/docs/versioned_docs/version-7.15.x/configuration/overview.md
index b145065a..7e47df92 100644
--- a/docs/versioned_docs/version-7.15.x/configuration/overview.md
+++ b/docs/versioned_docs/version-7.15.x/configuration/overview.md
@@ -217,7 +217,7 @@ When `--reverse-proxy` is enabled, configure `--trusted-proxy-ip` to the IPs or
| flag: `--reverse-proxy`
toml: `reverse_proxy` | bool | are we running behind a reverse proxy, controls whether headers like X-Real-IP are accepted and allows X-Forwarded-\{Proto,Host,Uri\} headers to be used on redirect selection | false |
| flag: `--trusted-proxy-ip`
toml: `trusted_proxy_ips` | string \| list | list of IPs or CIDR ranges allowed to supply `X-Forwarded-*` headers when `--reverse-proxy` is enabled. If not set, OAuth2 Proxy preserves backwards compatibility by trusting all source IPs (`0.0.0.0/0`, `::/0`) and logs a warning at startup. Configure this to your reverse proxy addresses to prevent forwarded header spoofing. | `"0.0.0.0/0", "::/0"` |
| flag: `--signature-key`
toml: `signature_key` | string | GAP-Signature request signature key (algorithm:secretkey) | |
-| flag: `--skip-auth-preflight`
toml: `skip_auth_preflight` | bool | will skip authentication for OPTIONS requests | false |
+| flag: `--skip-auth-preflight`
toml: `skip_auth_preflight` | bool | will skip authentication for OPTIONS requests handled directly by oauth2-proxy; does not apply to nginx `auth_request`, which calls `/oauth2/auth` via a separate GET subrequest | false |
| flag: `--skip-auth-regex`
toml: `skip_auth_regex` | string \| list | (DEPRECATED for `--skip-auth-route`) bypass authentication for requests paths that match (may be given multiple times) | |
| flag: `--skip-auth-route`
toml: `skip_auth_routes` | string \| list | bypass authentication for requests that match the method & path. Format: method=path_regex OR method!=path_regex. For all methods: path_regex OR !=path_regex | |
| flag: `--skip-jwt-bearer-tokens`
toml: `skip_jwt_bearer_tokens` | bool | will skip requests that have verified JWT bearer tokens (the token must have [`aud`](https://en.wikipedia.org/wiki/JSON_Web_Token#Standard_fields) that matches this client id or one of the extras from `extra-jwt-issuers`) | false |
diff --git a/oauthproxy_test.go b/oauthproxy_test.go
index b3271e5b..e7794743 100644
--- a/oauthproxy_test.go
+++ b/oauthproxy_test.go
@@ -1502,6 +1502,24 @@ func TestAuthSkippedForPreflightRequests(t *testing.T) {
assert.Equal(t, "response", rw.Body.String())
}
+func TestAuthOnlySkippedForPreflightRequests(t *testing.T) {
+ opts := baseTestOptions()
+ opts.SkipAuthPreflight = true
+ err := validation.Validate(opts)
+ assert.NoError(t, err)
+
+ proxy, err := NewOAuthProxy(opts, func(_ string) bool { return true })
+ assert.NoError(t, err)
+
+ rw := httptest.NewRecorder()
+ req, err := http.NewRequest(http.MethodOptions, opts.ProxyPrefix+authOnlyPath, nil)
+ assert.NoError(t, err)
+
+ proxy.ServeHTTP(rw, req)
+
+ assert.Equal(t, http.StatusAccepted, rw.Code)
+}
+
type SignatureAuthenticator struct {
auth hmacauth.HmacAuth
}
diff --git a/pkg/apis/options/options.go b/pkg/apis/options/options.go
index ac2b13c8..704f9b8e 100644
--- a/pkg/apis/options/options.go
+++ b/pkg/apis/options/options.go
@@ -129,7 +129,7 @@ func NewFlagSet() *pflag.FlagSet {
flagSet.StringSlice("skip-auth-route", []string{}, "bypass authentication for requests that match the method & path. Format: method=path_regex OR method!=path_regex. For all methods: path_regex OR !=path_regex")
flagSet.StringSlice("api-route", []string{}, "return HTTP 401 instead of redirecting to authentication server if token is not valid. Format: path_regex")
flagSet.Bool("skip-provider-button", false, "will skip sign-in-page to directly reach the next step: oauth/start")
- flagSet.Bool("skip-auth-preflight", false, "will skip authentication for OPTIONS requests")
+ flagSet.Bool("skip-auth-preflight", false, "will skip authentication for OPTIONS requests handled directly by oauth2-proxy (nginx auth_request uses a separate GET subrequest)")
flagSet.Bool("ssl-insecure-skip-verify", false, "skip validation of certificates presented when using HTTPS providers")
flagSet.Bool("skip-jwt-bearer-tokens", false, "will skip requests that have verified JWT bearer tokens (default false)")
flagSet.Bool("bearer-token-login-fallback", true, "if skip-jwt-bearer-tokens is set, fall back to normal login redirect with an invalid JWT. If false, 403 instead")