(next http.Handler)
| 227 | } |
| 228 | |
| 229 | func (s *Server) requireAuth(next http.Handler) http.Handler { |
| 230 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 231 | cfg := s.currentConfig() |
| 232 | expected := strings.TrimSpace(cfg.AuthToken) |
| 233 | if expected == "" { |
| 234 | next.ServeHTTP(w, r) |
| 235 | return |
| 236 | } |
| 237 | |
| 238 | provided := strings.TrimSpace(strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")) |
| 239 | if subtleCompare(provided, expected) || s.requestAuthenticatedViaSession(r) { |
| 240 | next.ServeHTTP(w, r) |
| 241 | return |
| 242 | } |
| 243 | |
| 244 | if strings.HasSuffix(r.URL.Path, "/watch") || r.URL.Path == "/watch" { |
| 245 | if !s.wsRejectLimiter.allow(s.clientAddressKey(r)) { |
| 246 | http.Error(w, "too many unauthorized websocket attempts", http.StatusTooManyRequests) |
| 247 | return |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | w.Header().Set("WWW-Authenticate", `Bearer realm="ZenNotes"`) |
| 252 | http.Error(w, "unauthorized", http.StatusUnauthorized) |
| 253 | }) |
| 254 | } |
| 255 | |
| 256 | // --- Responses --- |
| 257 |
nothing calls this directly
no test coverage detected