package web import ( "crypto/subtle" "net/http" "strings" ) // AuthMiddleware returns HTTP middleware that enforces authentication when // at least one of user/pass or token is configured. If all auth fields are // empty, the middleware is a no-op passthrough. // // Supported schemes: // - Bearer — matches the configured token // - Basic — matches the configured user:pass func AuthMiddleware(user, pass, token string) func(http.Handler) http.Handler { authEnabled := user != "" || token != "" return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !authEnabled { next.ServeHTTP(w, r) return } auth := r.Header.Get("Authorization") // Check bearer token first. if token != "" && strings.HasPrefix(auth, "Bearer ") { provided := strings.TrimPrefix(auth, "Bearer ") if subtle.ConstantTimeCompare([]byte(provided), []byte(token)) == 1 { next.ServeHTTP(w, r) return } } // Check basic auth. if user != "" { u, p, ok := r.BasicAuth() if ok && subtle.ConstantTimeCompare([]byte(u), []byte(user)) == 1 && subtle.ConstantTimeCompare([]byte(p), []byte(pass)) == 1 { next.ServeHTTP(w, r) return } } w.Header().Set("WWW-Authenticate", `Basic realm="keyhunter"`) http.Error(w, "Unauthorized", http.StatusUnauthorized) }) } }