package middleware import ( "net/http" "net/http/httptest" "testing" "github.com/seifghazi/claude-code-monitor/internal/config" ) func TestAuthAllowsLocalhostBypass(t *testing.T) { called := false handler := Auth(config.AuthConfig{ Enabled: true, Token: "secret", APIKeyHeader: "X-API-Key", AllowLocalhostBypass: true, })(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { called = true w.WriteHeader(http.StatusOK) })) req := httptest.NewRequest(http.MethodPost, "http://example.local/v1/messages", nil) req.RemoteAddr = "127.0.0.1:45678" rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) if !called { t.Fatal("expected localhost request to bypass auth") } } func TestAuthRejectsMissingCredentials(t *testing.T) { handler := Auth(config.AuthConfig{ Enabled: true, Token: "secret", APIKeyHeader: "X-API-Key", })(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) req := httptest.NewRequest(http.MethodPost, "http://example.local/v1/messages", nil) req.RemoteAddr = "10.1.2.3:45678" rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) if rr.Code != http.StatusUnauthorized { t.Fatalf("expected 401, got %d", rr.Code) } } func TestAuthAcceptsBearerAndAPIKey(t *testing.T) { testCases := []struct { name string setup func(*http.Request) header string }{ { name: "bearer", setup: func(r *http.Request) { r.Header.Set("Authorization", "Bearer secret") }, header: "Authorization", }, { name: "api-key", setup: func(r *http.Request) { r.Header.Set("X-API-Key", "secret") }, header: "X-API-Key", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { called := false handler := Auth(config.AuthConfig{ Enabled: true, Token: "secret", APIKeyHeader: "X-API-Key", })(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { called = true w.WriteHeader(http.StatusOK) })) req := httptest.NewRequest(http.MethodPost, "http://example.local/v1/messages", nil) req.RemoteAddr = "10.1.2.3:45678" tc.setup(req) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) if !called { t.Fatalf("expected %s auth to pass", tc.header) } if rr.Code != http.StatusOK { t.Fatalf("expected 200, got %d", rr.Code) } }) } } func TestAuthSkipsPublicDiscoveryRoutesAndOptions(t *testing.T) { handler := Auth(config.AuthConfig{ Enabled: true, Token: "secret", })(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })) publicPaths := []string{"/health", "/openapi.json", "/openapi.yaml"} for _, path := range publicPaths { req := httptest.NewRequest(http.MethodGet, "http://example.local"+path, nil) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("expected %s request to bypass auth, got %d", path, rr.Code) } } req := httptest.NewRequest(http.MethodOptions, "http://example.local/v1/messages", nil) rr := httptest.NewRecorder() handler.ServeHTTP(rr, req) if rr.Code != http.StatusOK { t.Fatalf("expected OPTIONS request to bypass auth, got %d", rr.Code) } }