diff --git a/internal/config/config.go b/internal/config/config.go index df81a40..5675523 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,7 +1,6 @@ package config import ( - "io/ioutil" "os" "strings" @@ -73,7 +72,7 @@ func Load() (*Config, error) { // Load from file if it exists if _, err := os.Stat(configPath); err == nil { - data, err := ioutil.ReadFile(configPath) + data, err := os.ReadFile(configPath) if err != nil { return nil, err } diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 9d06a14..6571180 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -3,6 +3,7 @@ package handlers import ( "encoding/json" "io" + "log" "net/http" "strconv" "strings" @@ -47,12 +48,19 @@ func New(db *database.DB, webAuthn *auth.WebAuthn, config *config.Config) *Handl func (h *Handlers) writeError(w http.ResponseWriter, message string, code int) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) - json.NewEncoder(w).Encode(map[string]string{"error": message}) + if err := json.NewEncoder(w).Encode(map[string]string{"error": message}); err != nil { + // If we can't encode the error response, log it + // Don't try to write another response as headers are already sent + log.Printf("Failed to encode error response: %v", err) + } } func (h *Handlers) writeJSON(w http.ResponseWriter, data interface{}) { w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(data) + if err := json.NewEncoder(w).Encode(data); err != nil { + // If encoding fails, try to send a simple error response + http.Error(w, "Failed to encode response", http.StatusInternalServerError) + } } // BeginRegistration starts the passkey registration process @@ -107,7 +115,10 @@ func (h *Handlers) BeginRegistration(w http.ResponseWriter, r *http.Request) { session, _ := h.store.Get(r, "webauthn-session") session.Values["challenge"] = sessionData.Challenge session.Values["user_id"] = user.ID - session.Save(r, w) + if err := session.Save(r, w); err != nil { + h.writeError(w, "Failed to save session", http.StatusInternalServerError) + return + } // Debug: log the options structure logrus.Debugf("WebAuthn options: %+v", options) @@ -182,7 +193,10 @@ func (h *Handlers) FinishRegistration(w http.ResponseWriter, r *http.Request) { // Clear session session.Values["challenge"] = nil session.Values["user_id"] = nil - session.Save(r, w) + if err := session.Save(r, w); err != nil { + log.Printf("Failed to save session: %v", err) + // Don't return error here as the main operation succeeded + } h.writeJSON(w, map[string]string{"status": "success"}) } @@ -233,7 +247,10 @@ func (h *Handlers) BeginLogin(w http.ResponseWriter, r *http.Request) { session, _ := h.store.Get(r, "webauthn-session") session.Values["challenge"] = sessionData.Challenge session.Values["user_id"] = webAuthnUser.GetUser().ID - session.Save(r, w) + if err := session.Save(r, w); err != nil { + h.writeError(w, "Failed to save session", http.StatusInternalServerError) + return + } h.writeJSON(w, options) } @@ -288,12 +305,18 @@ func (h *Handlers) FinishLogin(w http.ResponseWriter, r *http.Request) { authSession.Values["authenticated"] = true authSession.Values["user_id"] = user.ID authSession.Values["user_email"] = user.Email - authSession.Save(r, w) + if err := authSession.Save(r, w); err != nil { + h.writeError(w, "Failed to save auth session", http.StatusInternalServerError) + return + } // Clear webauthn session session.Values["challenge"] = nil session.Values["user_id"] = nil - session.Save(r, w) + if err := session.Save(r, w); err != nil { + log.Printf("Failed to save session: %v", err) + // Don't return error here as the main operation succeeded + } h.writeJSON(w, map[string]interface{}{ "status": "success", @@ -312,7 +335,10 @@ func (h *Handlers) Logout(w http.ResponseWriter, r *http.Request) { session.Values["user_id"] = nil session.Values["user_email"] = nil session.Options.MaxAge = -1 - session.Save(r, w) + if err := session.Save(r, w); err != nil { + log.Printf("Failed to save session during logout: %v", err) + // Don't return error here as logout should still succeed + } h.writeJSON(w, map[string]string{"status": "success"}) } diff --git a/main.go b/main.go index acda2ab..5e621fe 100644 --- a/main.go +++ b/main.go @@ -64,7 +64,9 @@ func main() { // Health check router.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{"status": "healthy"}) + if err := json.NewEncoder(w).Encode(map[string]string{"status": "healthy"}); err != nil { + http.Error(w, "Failed to encode response", http.StatusInternalServerError) + } }).Methods("GET") // Static files for admin UI diff --git a/main_test.go b/main_test.go index c1860d8..d7d8af8 100644 --- a/main_test.go +++ b/main_test.go @@ -16,7 +16,9 @@ func TestHealthEndpoint(t *testing.T) { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - w.Write([]byte(`{"status": "healthy"}`)) + if _, err := w.Write([]byte(`{"status": "healthy"}`)); err != nil { + t.Errorf("Failed to write response: %v", err) + } }) handler.ServeHTTP(rr, req)