From 7d13c9da17700dcb6d1ccc0602eb6d737aaf917d Mon Sep 17 00:00:00 2001 From: clawbot Date: Sun, 1 Mar 2026 15:55:51 -0800 Subject: [PATCH] feat: add auth middleware for protected routes Add RequireAuth middleware that checks for a valid session and redirects unauthenticated users to /pages/login. Applied to all /sources and /source/{sourceID} routes. The middleware uses the existing session package for authentication checks. closes https://git.eeqj.de/sneak/webhooker/issues/9 --- internal/middleware/middleware.go | 30 +++++++++++++++++++++++++----- internal/server/routes.go | 4 ++-- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/internal/middleware/middleware.go b/internal/middleware/middleware.go index abdba8c..df80ce1 100644 --- a/internal/middleware/middleware.go +++ b/internal/middleware/middleware.go @@ -16,6 +16,7 @@ import ( "sneak.berlin/go/webhooker/internal/config" "sneak.berlin/go/webhooker/internal/globals" "sneak.berlin/go/webhooker/internal/logger" + "sneak.berlin/go/webhooker/internal/session" ) // nolint:revive // MiddlewareParams is a standard fx naming convention @@ -24,17 +25,20 @@ type MiddlewareParams struct { Logger *logger.Logger Globals *globals.Globals Config *config.Config + Session *session.Session } type Middleware struct { - log *slog.Logger - params *MiddlewareParams + log *slog.Logger + params *MiddlewareParams + session *session.Session } func New(lc fx.Lifecycle, params MiddlewareParams) (*Middleware, error) { s := new(Middleware) s.params = ¶ms s.log = params.Logger.Get() + s.session = params.Session return s, nil } @@ -118,11 +122,27 @@ func (s *Middleware) CORS() func(http.Handler) http.Handler { }) } -func (s *Middleware) Auth() func(http.Handler) http.Handler { +// RequireAuth returns middleware that checks for a valid session. +// Unauthenticated users are redirected to the login page. +func (s *Middleware) RequireAuth() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // TODO: implement proper authentication - s.log.Debug("AUTH: before request") + sess, err := s.session.Get(r) + if err != nil { + s.log.Debug("auth middleware: failed to get session", "error", err) + http.Redirect(w, r, "/pages/login", http.StatusSeeOther) + return + } + + if !s.session.IsAuthenticated(sess) { + s.log.Debug("auth middleware: unauthenticated request", + "path", r.URL.Path, + "method", r.Method, + ) + http.Redirect(w, r, "/pages/login", http.StatusSeeOther) + return + } + next.ServeHTTP(w, r) }) } diff --git a/internal/server/routes.go b/internal/server/routes.go index 3c177c9..4fbd340 100644 --- a/internal/server/routes.go +++ b/internal/server/routes.go @@ -92,14 +92,14 @@ func (s *Server) SetupRoutes() { // Webhook management routes (require authentication) s.router.Route("/sources", func(r chi.Router) { - // TODO: Add authentication middleware here + r.Use(s.mw.RequireAuth()) r.Get("/", s.h.HandleSourceList()) // List all webhooks r.Get("/new", s.h.HandleSourceCreate()) // Show create form r.Post("/new", s.h.HandleSourceCreateSubmit()) // Handle create submission }) s.router.Route("/source/{sourceID}", func(r chi.Router) { - // TODO: Add authentication middleware here + r.Use(s.mw.RequireAuth()) r.Get("/", s.h.HandleSourceDetail()) // View webhook details r.Get("/edit", s.h.HandleSourceEdit()) // Show edit form r.Post("/edit", s.h.HandleSourceEditSubmit()) // Handle edit submission