internal/server/middleware.go (view raw)
1package server
2
3import (
4 "context"
5 "log/slog"
6 "net/http"
7 "strings"
8
9 "github.com/mjensen/weimar/internal/api"
10 "github.com/mjensen/weimar/internal/auth"
11)
12
13// requireAuth wraps a handler with session cookie authentication.
14// Unauthenticated requests receive a 401 JSON error.
15func (s *Server) requireAuth(next http.HandlerFunc) http.HandlerFunc {
16 return func(w http.ResponseWriter, r *http.Request) {
17 cookie, err := r.Cookie(auth.SessionCookieName)
18 if err != nil {
19 writeJSONError(w, http.StatusUnauthorized, "unauthorized")
20 return
21 }
22
23 user, err := s.auth.Authenticate(r.Context(), cookie.Value)
24 if err != nil {
25 slog.Debug("auth failed", "reason", err)
26 writeJSONError(w, http.StatusUnauthorized, "unauthorized")
27 return
28 }
29
30 ctx := context.WithValue(r.Context(), api.CtxKeyUser, user)
31 next(w, r.WithContext(ctx))
32 }
33}
34
35// writeJSONError writes a JSON error response.
36func writeJSONError(w http.ResponseWriter, status int, msg string) {
37 w.Header().Set("Content-Type", "application/json")
38 w.WriteHeader(status)
39 w.Write([]byte(`{"error":"` + strings.ReplaceAll(msg, `"`, `\"`) + `"}`))
40}