From 466755ddc25a1d7ccc5b479a20e5004467ccb375 Mon Sep 17 00:00:00 2001 From: "j.foucher" Date: Sat, 2 May 2026 11:26:38 +0200 Subject: [PATCH] DownloadUrl: tolerate Apache FastCGI stripping the Authorization header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OVH mutualisé serves PHP via FastCGI which strips the Authorization header by default for security. The user's curl test of GET /api/download-url/{ver} returned 401 even with -H "Authorization: Bearer " because $_SERVER['HTTP_AUTHORIZATION'] was empty server-side. Fix on two layers: 1. .htaccess at root re-injects the header into the Apache env so PHP can read it via the standard $_SERVER variable. The mod_rewrite one-liner `RewriteRule ^ - [E=HTTP_AUTHORIZATION:%1]` is the de- facto FastCGI workaround. 2. DownloadUrl.php now reads from any of: $_SERVER['HTTP_AUTHORIZATION'], $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] (passthrough variant), apache_request_headers(), getallheaders(). Belt and braces — works regardless of host config. Falls back to ?key= as before. Co-Authored-By: Claude Opus 4.7 (1M context) --- server/.htaccess | 6 ++++++ server/api/routes/DownloadUrl.php | 35 ++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/server/.htaccess b/server/.htaccess index 403e897..2ffea79 100644 --- a/server/.htaccess +++ b/server/.htaccess @@ -1,6 +1,12 @@ RewriteEngine On RewriteBase /PS_Launcher/ +# Forward du header Authorization vers PHP — Apache FastCGI le strippe par défaut +# sur OVH mutualisé. Sans ça, $_SERVER['HTTP_AUTHORIZATION'] est vide quand le +# client envoie "Authorization: Bearer ...". +RewriteCond %{HTTP:Authorization} ^(.+)$ +RewriteRule ^ - [E=HTTP_AUTHORIZATION:%1,L=0] + # HTTPS forcé (si le mutualisé OVH ne le force pas déjà) RewriteCond %{HTTPS} off RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] diff --git a/server/api/routes/DownloadUrl.php b/server/api/routes/DownloadUrl.php index c537e71..b9163ef 100644 --- a/server/api/routes/DownloadUrl.php +++ b/server/api/routes/DownloadUrl.php @@ -24,15 +24,34 @@ final class DownloadUrl } // Auth via Authorization: Bearer - $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? ''; - if (!preg_match('/^Bearer\s+(.+)$/i', $authHeader, $m)) { - // Fallback : certains hébergements masquent Authorization. On accepte aussi ?key= - $licenseKey = trim((string)($_GET['key'] ?? '')); - if ($licenseKey === '') { - Response::error('unauthorized', 'License key requise (Authorization: Bearer ... ou ?key=...)', 401); - } - } else { + // Apache OVH (et autres hébergements FastCGI) strippe parfois le header. On + // tente plusieurs sources : + // - $_SERVER['HTTP_AUTHORIZATION'] (cas standard) + // - $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] (mod_rewrite passthrough) + // - apache_request_headers() (présent quand mod_php) + // - getallheaders() (idem) + // - ?key=... (fallback explicite) + $authHeader = $_SERVER['HTTP_AUTHORIZATION'] + ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] + ?? ''; + if ($authHeader === '' && function_exists('apache_request_headers')) { + $h = apache_request_headers(); + $authHeader = $h['Authorization'] ?? $h['authorization'] ?? ''; + } + if ($authHeader === '' && function_exists('getallheaders')) { + $h = getallheaders(); + $authHeader = $h['Authorization'] ?? $h['authorization'] ?? ''; + } + + $licenseKey = ''; + if (preg_match('/^Bearer\s+(.+)$/i', $authHeader, $m)) { $licenseKey = trim($m[1]); + } else { + $licenseKey = trim((string)($_GET['key'] ?? '')); + } + if ($licenseKey === '') { + Response::error('unauthorized', + 'License key requise (Authorization: Bearer ... ou ?key=...)', 401); } $db = Db::get($config);