43 lines
1.6 KiB
Go
43 lines
1.6 KiB
Go
// Package middleware enthält HTTP-Middleware — das sind Funktionen die sich
|
|
// "vor" den eigentlichen Handlern schalten und z.B. Authentifizierung prüfen.
|
|
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"wiki/handler"
|
|
)
|
|
|
|
// RequireTeamOrAdminKey schützt /api/upload, /api/delete und /mcp.
|
|
//
|
|
// Der Bearer-Key wird gegen die TeamRegistry aufgelöst: ein Team-Key beschränkt
|
|
// den Request auf das eigene Team, der globale Admin-Key (ADMIN_TOKEN) erlaubt
|
|
// Zugriff auf jedes Team, muss dafür aber explizit sagen welches (siehe api.go:
|
|
// Formfeld/Query-Param "team"; mcp.go: Header "X-Wiki-Team").
|
|
//
|
|
// Das aufgelöste Team (oder der Admin-Status) landet im Request-Context —
|
|
// siehe handler.WithTeam / handler.TeamFromContext.
|
|
func RequireTeamOrAdminKey(next http.Handler, registry *handler.TeamRegistry) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
authHeader := r.Header.Get("Authorization")
|
|
if !strings.HasPrefix(authHeader, "Bearer ") {
|
|
http.Error(w, "Authorization header fehlt", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
key := strings.TrimPrefix(authHeader, "Bearer ")
|
|
|
|
// Timing-sicherer Vergleich passiert bereits innerhalb von registry.Resolve
|
|
// (subtle.ConstantTimeCompare, siehe registry.go) — verhindert dass ein
|
|
// Angreifer anhand der Antwortzeit erraten kann wie viele Zeichen seines
|
|
// Keys korrekt sind.
|
|
team, isAdmin, ok := registry.Resolve(key)
|
|
if !ok {
|
|
http.Error(w, "Ungültiger Key", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
next.ServeHTTP(w, r.WithContext(handler.WithTeam(r.Context(), team, isAdmin)))
|
|
})
|
|
}
|