From dcdda5689df4b935cb9585b58ce191216101b705 Mon Sep 17 00:00:00 2001 From: Michael Geers Date: Fri, 12 Jun 2026 17:29:32 +0200 Subject: [PATCH] Auth: coexist with reverse proxy Authorization header (#30757) --- server/http_auth.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/server/http_auth.go b/server/http_auth.go index 04cf7c936..e05071179 100644 --- a/server/http_auth.go +++ b/server/http_auth.go @@ -66,9 +66,13 @@ func updatePasswordHandler(authObject auth.Auth) http.HandlerFunc { } } -// apiKeyFromRequest returns the API key from the Authorization: Bearer header, or "" if absent +// apiKeyFromRequest returns the API key from the Authorization: Bearer header, or "" if absent. +// A non-Bearer Authorization header (e.g. Basic auth injected by a reverse proxy) is ignored. func apiKeyFromRequest(r *http.Request) string { - token, _ := strings.CutPrefix(r.Header.Get("Authorization"), "Bearer ") + token, found := strings.CutPrefix(r.Header.Get("Authorization"), "Bearer ") + if !found { + return "" + } return token } @@ -80,12 +84,17 @@ func jwtFromCookie(r *http.Request) string { return "" } -// validateAuth accepts a valid API key from the Authorization header, or a valid session JWT from the auth cookie +// validateAuth accepts a valid API key from the Authorization header, or a valid session JWT from the auth cookie. +// Any single valid credential grants access, so evcc coexists with a reverse proxy that injects its own +// Authorization header or with clients that forward an unrelated bearer token. func validateAuth(authObject auth.Auth, r *http.Request) bool { - if key := apiKeyFromRequest(r); key != "" { - return authObject.ValidateApiKey(key) + if key := apiKeyFromRequest(r); key != "" && authObject.ValidateApiKey(key) { + return true } - return authObject.ValidateJwtToken(jwtFromCookie(r)) + if jwt := jwtFromCookie(r); jwt != "" && authObject.ValidateJwtToken(jwt) { + return true + } + return false } // requireAdminPassword passes when --disable-auth is set or the supplied password matches.