Use the Chi BasicAuth middleware

This commit is contained in:
Tobias Gesellchen
2026-02-21 00:42:07 +01:00
parent a886518cad
commit aced0f3f81
3 changed files with 2 additions and 126 deletions
-23
View File
@@ -1,23 +0,0 @@
package handlers
import (
"crypto/subtle"
"net/http"
)
// BasicAuthMiddleware returns a chi middleware that enforces HTTP Basic Authentication.
func BasicAuthMiddleware(username, password string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
u, p, ok := r.BasicAuth()
if !ok ||
subtle.ConstantTimeCompare([]byte(u), []byte(username)) != 1 ||
subtle.ConstantTimeCompare([]byte(p), []byte(password)) != 1 {
w.Header().Set("WWW-Authenticate", `Basic realm="Management API"`)
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
}
@@ -1,102 +0,0 @@
package handlers
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestBasicAuthMiddleware_ValidCredentials(t *testing.T) {
handler := BasicAuthMiddleware("admin", "secret123")(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("OK"))
}))
req := httptest.NewRequest(http.MethodGet, "/mgmt/test", nil)
req.SetBasicAuth("admin", "secret123")
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
if rr.Code != http.StatusOK {
t.Errorf("expected status %d, got %d", http.StatusOK, rr.Code)
}
if rr.Body.String() != "OK" {
t.Errorf("expected body 'OK', got %q", rr.Body.String())
}
}
func TestBasicAuthMiddleware_WrongUsername(t *testing.T) {
handler := BasicAuthMiddleware("admin", "secret123")(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Error("handler should not be called with wrong username")
}))
req := httptest.NewRequest(http.MethodGet, "/mgmt/test", nil)
req.SetBasicAuth("wrong", "secret123")
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
if rr.Code != http.StatusUnauthorized {
t.Errorf("expected status %d, got %d", http.StatusUnauthorized, rr.Code)
}
if rr.Header().Get("WWW-Authenticate") == "" {
t.Error("expected WWW-Authenticate header to be set")
}
}
func TestBasicAuthMiddleware_WrongPassword(t *testing.T) {
handler := BasicAuthMiddleware("admin", "secret123")(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Error("handler should not be called with wrong password")
}))
req := httptest.NewRequest(http.MethodGet, "/mgmt/test", nil)
req.SetBasicAuth("admin", "wrongpass")
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
if rr.Code != http.StatusUnauthorized {
t.Errorf("expected status %d, got %d", http.StatusUnauthorized, rr.Code)
}
if rr.Header().Get("WWW-Authenticate") == "" {
t.Error("expected WWW-Authenticate header to be set")
}
}
func TestBasicAuthMiddleware_MissingAuthHeader(t *testing.T) {
handler := BasicAuthMiddleware("admin", "secret123")(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Error("handler should not be called without auth header")
}))
req := httptest.NewRequest(http.MethodGet, "/mgmt/test", nil)
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
if rr.Code != http.StatusUnauthorized {
t.Errorf("expected status %d, got %d", http.StatusUnauthorized, rr.Code)
}
if rr.Header().Get("WWW-Authenticate") == "" {
t.Error("expected WWW-Authenticate header to be set")
}
}
func TestBasicAuthMiddleware_EmptyCredentials(t *testing.T) {
handler := BasicAuthMiddleware("admin", "secret123")(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Error("handler should not be called with empty credentials")
}))
req := httptest.NewRequest(http.MethodGet, "/mgmt/test", nil)
req.SetBasicAuth("", "")
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
if rr.Code != http.StatusUnauthorized {
t.Errorf("expected status %d, got %d", http.StatusUnauthorized, rr.Code)
}
if rr.Header().Get("WWW-Authenticate") == "" {
t.Error("expected WWW-Authenticate header to be set")
}
}
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
// BasicAuthMgmt returns a Basic Auth middleware using the server's management credentials.
@@ -16,7 +17,7 @@ func (s *Server) BasicAuthMgmt() func(http.Handler) http.Handler {
password := s.mgmtPassword
s.mu.RUnlock()
return BasicAuthMiddleware(username, password)
return middleware.BasicAuth("Management API", map[string]string{username: password})
}
// HandleMgmtListSpeakers returns discovered speakers for the given account.