rmm2/backend/api/middleware.go

91 lines
2.3 KiB
Go

package api
import (
"context"
"log"
"net/http"
"strings"
"time"
)
type contextKey string
const UserContextKey contextKey = "user"
// APIKeyAuth - Middleware fuer API-Key Authentifizierung
func APIKeyAuth(validKeys []string, next http.Handler) http.Handler {
keySet := make(map[string]bool, len(validKeys))
for _, k := range validKeys {
keySet[k] = true
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
key := r.Header.Get("X-API-Key")
if key == "" {
key = r.URL.Query().Get("api_key")
}
if key == "" || !keySet[key] {
http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
// CombinedAuth - API-Key ODER JWT Token
func CombinedAuth(validKeys []string, auth *AuthHandler, next http.Handler) http.Handler {
keySet := make(map[string]bool, len(validKeys))
for _, k := range validKeys {
keySet[k] = true
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Try API key first
key := r.Header.Get("X-API-Key")
if key == "" {
key = r.URL.Query().Get("api_key")
}
if key != "" && keySet[key] {
next.ServeHTTP(w, r)
return
}
// Try JWT
authHeader := r.Header.Get("Authorization")
if strings.HasPrefix(authHeader, "Bearer ") {
token := strings.TrimPrefix(authHeader, "Bearer ")
claims, err := auth.ValidateToken(token)
if err == nil {
ctx := context.WithValue(r.Context(), UserContextKey, claims)
next.ServeHTTP(w, r.WithContext(ctx))
return
}
}
http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
})
}
// CORS Middleware
func CORS(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-API-Key")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}
// Logging - Request-Logging Middleware
func Logging(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf("%s %s %s", r.Method, r.URL.Path, time.Since(start))
})
}