View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 20646 | Bug reports | Question editor | public | 2026-08-11 18:56 | 2026-08-13 18:12 |
| Reporter | grinrus | Assigned To | tibor.pacalat | ||
| Priority | none | Severity | block | ||
| Status | closed | Resolution | duplicate | ||
| Product Version | 7.0.x | ||||
| Summary | 20646: REST API returns 401 under HTTP/2: case-sensitive Authorization header lookup breaks the new question editor | ||||
| Description | The REST API rejects valid bearer tokens when the request arrives over HTTP/2, because the Authorization header is looked up with a case-sensitive array key. As a consequence the new question editor never loads: it hangs forever on "Checking permissions...". ROOT CAUSE application/libraries/Api/Rest/Endpoint/EndpointFactory.php, getAuthBearerToken() (~line 226 on master):
The casing of the keys returned by getallheaders() depends on the server stack:
HTTP/2 (RFC 9113, section 8.2) requires all header field names to be transmitted in lowercase. So on Apache + mod_php + HTTP/2 the key is "authorization", the isset() check fails, no token is extracted, and every authenticated REST call returns 401. HTTP header field names are case-insensitive by specification (RFC 9110, section 5.1), so a case-sensitive lookup is incorrect regardless of the HTTP version. WHY IT IS HARD TO DIAGNOSE The React editor bootstraps by calling GET /rest/v1/user-permissions. PermissionsProvider has no visible failure path for a rejected request, so the UI stays on the "Checking permissions..." spinner indefinitely. There is no error message, nothing in the application log, and the admin session itself is perfectly valid. The practical effect is that the survey editor is completely unusable - surveys cannot be created, edited or activated - while everything else in the admin interface works normally. EVIDENCE Same token, same server, only the HTTP version differs (measured with PHP cURL and CURLOPT_HTTP_VERSION):
The token itself is valid and correctly stored in lime_sessions. Passing the same token via the ?authToken= query parameter - the documented fallback in getAuthToken() - also returns 200 under HTTP/2, which confirms that only the header lookup is at fault. Header name as seen by PHP for the very same request:
SUGGESTED FIX Normalise the keys before the lookup - the approach recommended by the PHP manual for getallheaders():
Verified on our installation: after this change the editor loads and surveys can be created and activated normally over HTTP/2. A secondary improvement worth considering: PermissionsProvider should surface a failed permissions request instead of showing the spinner forever. The silent failure is what made this take a full day to track down. ADDITIONAL NOTES The LimeSurvey 7 Question Editor documentation lists urlFormat => 'path' and URL rewriting as the requirements for the new editor. Both were satisfied here. Neither the Authorization header nor HTTP/2 is mentioned, and there is no troubleshooting entry for the hanging "Checking permissions..." screen. Note that on many shared hosting providers HTTP/2 is enabled automatically together with HTTPS and cannot be turned off per site, so affected users have no configuration-level workaround and must patch the file. A similar symptom is reported at https://forum.cloudron.io/topic/15623/new-question-editor-require-config.php-change but with a different root cause (404 on /rest/v1/version-info caused by packaging routing); it was fixed by the packager and never reported upstream. ON THE REQUEST TO ATTACH AN EXAMPLE SURVEY No .lss file is attached because the issue does not depend on survey content. The failing call is GET /rest/v1/user-permissions, which the editor makes before any survey is loaded, so it reproduces with any survey - or with none at all, by opening the editor on a freshly created installation. | ||||
| Steps To Reproduce |
Expected: the editor loads. Actual: the page stays on "Checking permissions..." forever. Browser devtools show To confirm the cause without patching anything, call the same endpoint with the same | ||||
| Tags | No tags attached. | ||||
| Bug heat | 0 | ||||
| Complete LimeSurvey version number (& build) | 7.0.9+260812 | ||||
| I will donate to the project if issue is resolved | No | ||||
| Story point estimate | 0 | ||||
| Browser | Chrome (any; reproducible with curl --http2) | ||||
| Database type & version | MySQL 8.4.8 | ||||
| Server OS (if known) | Ubuntu 22.04 | ||||
| Webserver software & version (if known) | Apache 2.4.63 behind nginx 1.21.1 (HTTP/2 terminated by nginx) | ||||
| PHP Version | 8.2.28 (SAPI: apache2handler) | ||||
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-08-11 18:56 | grinrus | New Issue | |
| 2026-08-12 10:26 | tibor.pacalat | Relationship added | duplicate of 20623 |
| 2026-08-12 13:03 | tibor.pacalat | Assigned To | => tibor.pacalat |
| 2026-08-12 13:03 | tibor.pacalat | Status | new => resolved |
| 2026-08-12 13:03 | tibor.pacalat | Resolution | open => duplicate |
| 2026-08-13 18:12 | c_schmitz | Status | resolved => closed |