fix: resolve Authorization via the SDK's getallheaders() fallback in Status_Handler - #19
Merged
Merged
Conversation
…Status_Handler Apache withholds the Authorization header from the CGI-style $_SERVER variables unless rewrite config re-exports it. Hosts whose server config lacks WordPress's E=HTTP_AUTHORIZATION rule (e.g. WP Engine) therefore never delivered the backend's challenge JWT to the status handler, so every probe received the 404 decoy and self-report failed. Delegate to RequestContext::resolveAuthorizationHeader() (SDK 1.4.0-beta.10, #24) which falls back to getallheaders().
There was a problem hiding this comment.
Pull request overview
Fixes the status endpoint’s Authorization header resolution on hosts where Apache withholds Authorization from $_SERVER, by delegating to the SDK’s header resolver and adding regression tests to cover the fallback behavior.
Changes:
- Bump
getsupertab/connect-sdk-phpfrom1.4.0-beta.9to1.4.0-beta.10to useRequestContext::resolveAuthorizationHeader(). - Update
Status_Handler::get_authorization_header()to fall back to raw request headers (viagetallheaders()seam) when$_SERVERlacks the header. - Add regression tests for raw-header fallback,
$_SERVERprecedence, and empty result when absent.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
src/class-status-handler.php |
Delegates Authorization header resolution to the SDK and adds a protected raw-header seam. |
tests/StatusHandlerTest.php |
Adds regression tests for Authorization header resolution and raw-header fallback. |
composer.json |
Updates SDK dependency version constraint to 1.4.0-beta.10. |
composer.lock |
Locks SDK to v1.4.0-beta.10 and updates the lockfile hash/metadata. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ion protected PHPUnit here does not back up superglobals, so a failed assertion in a test that seeds HTTP_AUTHORIZATION would leak it into later tests. Snapshot/restore the two auth keys around every test, expose the now- protected get_authorization_header() through the test subclass, and mirror the parent constructor types in the anonymous class.
github-actions Bot
pushed a commit
that referenced
this pull request
Jul 14, 2026
# [1.3.0-beta.9](v1.3.0-beta.8...v1.3.0-beta.9) (2026-07-14) ### Bug Fixes * resolve Authorization via the SDK's getallheaders() fallback in Status_Handler ([#19](#19)) ([d515452](d515452)), closes [getsupertab/connect-sdk-php#24](getsupertab/connect-sdk-php#24)
|
🎉 This PR is included in version 1.3.0-beta.9 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR fixes the self-report status endpoint silently serving the 404 decoy to the backend's challenge probes on hosts where Apache withholds the
Authorizationheader from$_SERVER— which is why the live self-report check fails for sites on WP Engine despite running 1.3.0-beta.8.Context
The backend's health check probes
/.well-known/supertab/statuswith a challenge JWT in theAuthorizationheader.Status_Handler::get_authorization_header()read only$_SERVER['HTTP_AUTHORIZATION']/REDIRECT_HTTP_AUTHORIZATION— but Apache withholdsAuthorizationfrom the CGI-style$_SERVERvariables (a CGI-era behavior), whilegetallheaders()still exposes it. Since every verification failure fails closed to the decoy, the endpoint looked healthy from outside while every valid probe was rejected.Stock WordPress masks this: since WP 5.6 the core
.htaccessrewrite block includesRewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}], which re-exports the header. Hosts that generate their own server config without that rule (WP Engine among them) hit the bug. That's also why the original wp-env verification couldn't catch it — wp-env's stock.htaccesscarries the compensating rule.This is the same defect fixed in the SDK by getsupertab/connect-sdk-php#24, found live on the vanilla-PHP self-report demo; the plugin duplicated the pre-fix header reading instead of going through the SDK.
Key Changes
1.4.0-beta.9→1.4.0-beta.10, which shipsRequestContext::resolveAuthorizationHeader()(and fixes the same bug inside the SDK's ownhandleRequest()path used byBot_Protectionfor license-token checks).Status_Handler::get_authorization_header()now delegates to the SDK resolver:$_SERVERwins when populated, otherwise the raw request headers are searched case-insensitively. New protectedget_raw_request_headers()seam wrapsgetallheaders()(guarded byfunction_exists; unavailable under the CLI SAPI) so tests can inject headers.$_SERVERlacks the header,$_SERVERprecedence, and empty result when absent everywhere.Verified end-to-end in wp-env (Apache + mod_php) via A/B: with the core
.htaccessauth rule removed to mirror affected hosts, the old code never delivered the bearer to the verifier (no JWKS activity, decoy served); with this fix the same probe reachesStatusChallengeVerifier, fetches the platform JWKS, and fails only on the (deliberately) unverifiable test token — decoy behavior for invalid/missing challenges is unchanged.