package handler import ( "crypto/subtle" "fmt" "net/http" ) // BasicAuthConfig configures HTTP Basic authentication middleware. type BasicAuthConfig struct { Username string Password string Realm string } // BasicAuthMiddleware protects routes with HTTP Basic authentication. // If credentials are not configured, all requests are denied. func BasicAuthMiddleware(cfg BasicAuthConfig) func(http.Handler) http.Handler { realm := cfg.Realm if realm == "" { realm = "Restricted" } return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { username, password, ok := r.BasicAuth() if !ok || !basicAuthCredentialsMatch(username, password, cfg.Username, cfg.Password) { w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s", charset="UTF-8"`, realm)) writeJSON(w, http.StatusUnauthorized, map[string]string{ "error": "unauthorized", }) return } next.ServeHTTP(w, r) }) } } func basicAuthCredentialsMatch(gotUser, gotPass, wantUser, wantPass string) bool { if wantUser == "" || wantPass == "" { return false } userOK := subtle.ConstantTimeCompare([]byte(gotUser), []byte(wantUser)) == 1 passOK := subtle.ConstantTimeCompare([]byte(gotPass), []byte(wantPass)) == 1 return userOK && passOK }