Files
upstream-centrifugo/internal/middleware/auth.go
upstream-mirror b352a9a30d
Some checks failed
test / Lint (push) Failing after 3s
test / Test with Go 1.26.8 (push) Failing after 2s
snapshot of https://github.com/centrifugal/centrifugo.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 01:17:21 +05:00

59 lines
1.5 KiB
Go

package middleware
import (
"net/http"
"strings"
"github.com/centrifugal/centrifugo/v6/internal/tools"
"github.com/rs/zerolog/log"
)
// APIKeyAuth middleware authorizes request using API key authorization.
// It first tries to use Authorization header to extract API key
// (Authorization: apikey <KEY>), then checks for api_key URL query parameter.
// If key not found or invalid then 401 response code is returned.
type APIKeyAuth struct {
key string
}
func NewAPIKeyAuth(key string) *APIKeyAuth {
return &APIKeyAuth{key: key}
}
func (a *APIKeyAuth) Middleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if a.key == "" {
log.Error().Msg("API key is empty")
w.WriteHeader(http.StatusUnauthorized)
return
}
authValid := false
authHeaderValue := r.Header.Get("X-API-Key")
if authHeaderValue != "" {
if tools.SecureCompareString(a.key, authHeaderValue) {
authValid = true
}
} else {
authHeaderAuthorization := r.Header.Get("Authorization")
if authHeaderAuthorization != "" {
parts := strings.Fields(authHeaderAuthorization)
if len(parts) == 2 && strings.ToLower(parts[0]) == "apikey" && tools.SecureCompareString(a.key, parts[1]) {
authValid = true
}
}
}
if !authValid && r.URL.RawQuery != "" {
// Check URL param.
if tools.SecureCompareString(a.key, r.URL.Query().Get("api_key")) {
authValid = true
}
}
if !authValid {
w.WriteHeader(http.StatusUnauthorized)
return
}
h.ServeHTTP(w, r)
})
}