@@ -834,8 +834,20 @@ func NewProcessCookieTest(opts ProcessCookieTestOpts, modifiers ...OptionsModifi
834834 return nil, err
835835 }
836836 testProvider := &TestProvider{
837− ProviderData: &providers.ProviderData{},
838− ValidToken: opts.providerValidateCookieResponse,
837+ ProviderData: &providers.ProviderData{
838+ ProviderName: "Test Provider",
839+ LoginURL: &url.URL{
840+ Scheme: "http",
841+ Host: "localhost",
842+ Path: "/oauth/authorize",
843+ },
844+ RedeemURL: &url.URL{
845+ Scheme: "http",
846+ Host: "localhost",
847+ Path: "/oauth/token",
848+ },
849+ },
850+ ValidToken: opts.providerValidateCookieResponse,
839851 }
840852
841853 groups := pcTest.opts.Providers[0].AllowedGroups
@@ -1112,6 +1124,35 @@ func TestAuthOnlyEndpointUnauthorizedOnNoCookieSetError(t *testing.T) {
11121124 assert.Equal(t, "Unauthorized\n", string(bodyBytes))
11131125}
11141126
1127+// TestAuthOnlyEndpointRedirectWithSkipProviderButton tests that when SkipProviderButton
1128+// is true and no session exists, the /auth endpoint should return a 302 redirect
1129+// to the OAuth provider instead of 401. This is important for nginx auth_request
1130+// architecture where 401 triggers error_page handling which can break the redirect flow.
1131+// See: https://github.com/oauth2-proxy/oauth2-proxy/issues/334
1132+func TestAuthOnlyEndpointRedirectWithSkipProviderButton(t *testing.T) {
1133+ test, err := NewAuthOnlyEndpointTest("", func(opts *options.Options) {
1134+ opts.SkipProviderButton = true
1135+ })
1136+ if err != nil {
1137+ t.Fatal(err)
1138+ }
1139+
1140+ test.proxy.ServeHTTP(test.rw, test.req)
1141+
1142+ // With SkipProviderButton=true and no session, should return 302 redirect
1143+ // to OAuth provider, NOT 401 Unauthorized
1144+ assert.Equal(t, http.StatusFound, test.rw.Code)
1145+ location := test.rw.Header().Get("Location")
1146+ assert.NotEmpty(t, location, "Expected Location header for redirect")
1147+
1148+ // Verify the redirect points to the OAuth provider's authorize endpoint
1149+ // and contains key OAuth parameters
1150+ assert.Contains(t, location, "/oauth/authorize", "Expected redirect to OAuth authorize endpoint")
1151+ assert.Contains(t, location, "client_id=", "Expected client_id in redirect URL")
1152+ assert.Contains(t, location, "redirect_uri=", "Expected redirect_uri in redirect URL")
1153+ assert.Contains(t, location, "state=", "Expected state parameter in redirect URL")
1154+}
1155+
11151156func TestAuthOnlyEndpointUnauthorizedOnExpiration(t *testing.T) {
11161157 test, err := NewAuthOnlyEndpointTest("", func(opts *options.Options) {
11171158 opts.Cookie.Expire = time.Duration(24) * time.Hour