revert: "fix: skip provider button auth only redirect (#3309)" (#3314)

This reverts commit 9c61c49ec2.

The original fix broke nginx deployments using `auth_request`. When `/oauth2/auth` returns 302,
nginx's `auth_request` module treats this as an internal error:

    [error] auth request unexpected status: 302 while sending to client

nginx then returns **500 Internal Server Error** to the browser.

> If the subrequest returns a 2xx response code, the access is allowed. If it returns 401 or 403,
> the access is denied with the corresponding error code. Any other response code returned by the
> subrequest is considered an error.
https://nginx.org/en/docs/http/ngx_http_auth_request_module.html

The nginx `auth_request` module has strict semantics (non-negotiable):

| Subrequest status | nginx behavior |
|---|---|
| 2xx | Allow request |
| 401 / 403 | Deny → trigger `error_page` |
| **Any other status** | **Internal error → 500** |

The `/oauth2/auth` endpoint is used as a **policy oracle** (yes/no decision),
not as a browser-facing endpoint. It cannot return redirects.

Any nginx deployment with:
- `skip-provider-button=true`
- Using `auth_request` directive

Will receive 500 errors instead of the expected authentication flow.

The correct fix for #334 is a **documentation update**, not a code change:

```nginx
error_page 401 = @oauth2_signin;

location @oauth2_signin {
    return 302 /oauth2/sign_in?rd=$scheme://$host$request_uri;
}
```

This keeps `/oauth2/auth` as a pure 401/2xx oracle and lets nginx perform the proper 302 redirect to the browser.

- Original Issue: #334
- Regression introduced in PR: #3309

Signed-off-by: Stefan Markmann <stefan@markmann.net>
Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
This commit is contained in:
Stefan Markmann
2026-01-18 00:36:08 +01:00
committed by GitHub
co-authored by Jan Larwig
parent 7bf586c898
commit cf5d34acf6
5 changed files with 7 additions and 54 deletions
+2 -43
View File
@@ -834,20 +834,8 @@ func NewProcessCookieTest(opts ProcessCookieTestOpts, modifiers ...OptionsModifi
return nil, err
}
testProvider := &TestProvider{
ProviderData: &providers.ProviderData{
ProviderName: "Test Provider",
LoginURL: &url.URL{
Scheme: "http",
Host: "localhost",
Path: "/oauth/authorize",
},
RedeemURL: &url.URL{
Scheme: "http",
Host: "localhost",
Path: "/oauth/token",
},
},
ValidToken: opts.providerValidateCookieResponse,
ProviderData: &providers.ProviderData{},
ValidToken: opts.providerValidateCookieResponse,
}
groups := pcTest.opts.Providers[0].AllowedGroups
@@ -1124,35 +1112,6 @@ func TestAuthOnlyEndpointUnauthorizedOnNoCookieSetError(t *testing.T) {
assert.Equal(t, "Unauthorized\n", string(bodyBytes))
}
// TestAuthOnlyEndpointRedirectWithSkipProviderButton tests that when SkipProviderButton
// is true and no session exists, the /auth endpoint should return a 302 redirect
// to the OAuth provider instead of 401. This is important for nginx auth_request
// architecture where 401 triggers error_page handling which can break the redirect flow.
// See: https://github.com/oauth2-proxy/oauth2-proxy/issues/334
func TestAuthOnlyEndpointRedirectWithSkipProviderButton(t *testing.T) {
test, err := NewAuthOnlyEndpointTest("", func(opts *options.Options) {
opts.SkipProviderButton = true
})
if err != nil {
t.Fatal(err)
}
test.proxy.ServeHTTP(test.rw, test.req)
// With SkipProviderButton=true and no session, should return 302 redirect
// to OAuth provider, NOT 401 Unauthorized
assert.Equal(t, http.StatusFound, test.rw.Code)
location := test.rw.Header().Get("Location")
assert.NotEmpty(t, location, "Expected Location header for redirect")
// Verify the redirect points to the OAuth provider's authorize endpoint
// and contains key OAuth parameters
assert.Contains(t, location, "/oauth/authorize", "Expected redirect to OAuth authorize endpoint")
assert.Contains(t, location, "client_id=", "Expected client_id in redirect URL")
assert.Contains(t, location, "redirect_uri=", "Expected redirect_uri in redirect URL")
assert.Contains(t, location, "state=", "Expected state parameter in redirect URL")
}
func TestAuthOnlyEndpointUnauthorizedOnExpiration(t *testing.T) {
test, err := NewAuthOnlyEndpointTest("", func(opts *options.Options) {
opts.Cookie.Expire = time.Duration(24) * time.Hour