Skip to content

Restore update checks and magic login on sites where the API key lives in the environment - #28

Closed
nabil1440 wants to merge 1 commit into
developfrom
fix/api-key-env-fallback
Closed

nabil1440 wants to merge 1 commit into
developfrom
fix/api-key-env-fallback

Conversation

@nabil1440

Copy link
Copy Markdown
Contributor

What is wrong

  • FlyWP talks to each WordPress site through a helper plugin.
  • The plugin needs an API key. It reads that key from a PHP constant.
  • On a Bedrock site there is no wp-config.php. FlyWP writes the key into the .env file.
  • The .env value becomes a constant only when a config file declares it.
  • A repository built from upstream roots/bedrock does not declare it.

What the customer sees

  • The key is present and correct. The plugin cannot see it.
  • The plugin switches itself off.
  • A request to /fly-api/* answers with the site home page and a success code.
  • To a caller that looks like a working site. It is not.
  • The update check fails. Magic login fails.

What this changes

  • The plugin reads the key from the environment when the constant is empty.
  • It reads getenv(), $_ENV and $_SERVER, because the loaders disagree on which they fill.
  • It removes the slashes WordPress adds to $_SERVER. Without this a key that holds a quote or a backslash could never match.
  • A site with no key now answers /fly-api/* with JSON. It no longer answers with the theme.
  • The ping answer says whether the plugin found a key.
  • The plugin stands down when a second copy is already loaded, so two copies cannot break a site.

Decisions worth knowing

  • The ping answer changed on purpose. The route is now registered whether or not a key was found. A success code alone therefore no longer proves the integration works. Read the has_key field.
  • A request with a wrong token still answers 404, not 401. This is unchanged and deliberate. A different answer would tell an anonymous caller that a site is managed by FlyWP.
  • The key is not sanitized. It is a credential compared with hash_equals(). Sanitizing could change the value and break authentication.

Tests

  • The resolver is a separate class with no WordPress functions in it, so the existing unit suite covers it.
  • 46 tests pass. PHPCS reports no issues.

Order

  • This release alone repairs no site. On Bedrock the plugin comes from Composer, and FlyWP cannot update it.
  • The release reaches a Bedrock site only after the update path lands in the app.

…nment

The plugin read FLYWP_API_KEY as a PHP constant and nothing else. Classic
WordPress writes that constant into wp-config.php, so it is always set. Bedrock
has no wp-config.php: FlyWP writes the key into .env, and the constant exists
only when a config file declares it with Config::define(). A repository built
from upstream roots/bedrock does not declare it.

On those sites the key was present and correct, and the plugin could not see
it. has_key() returned false, init_plugin() stopped, and the router was never
built. WordPress then dropped the unknown `fly-api` query variable and served
the front page with a 200, which reads to a caller as a working site.

- Read the key from getenv(), $_ENV and $_SERVER when the constant is empty.
  The loaders disagree on which they populate: bedrock-starter fills the first
  two, a repository using createImmutable fills neither.
- Unslash the $_SERVER value. wp_magic_quotes() escapes that superglobal before
  any plugin loads, so a key holding a quote or a backslash would never match
  the bearer token, which Api::get_bearer_token() unslashes.
- Load the router and the API above the key gate, so an unkeyed site answers
  with JSON instead of the theme. This exposes no new route: ping was already
  unauthenticated, and every other route stays behind the bearer check.
- Report has_key in the ping body. Now that the route is registered whether or
  not a key was found, a 200 alone no longer means the integration works.
- Stand down when this plugin is already loaded from another directory, so two
  copies cannot declare the same class twice.

The resolver is a separate class with no WordPress functions in it, so the
behaviour is covered by the existing unit suite rather than left untested.

Refs flywp/flywp-app#2481, flywp/flywp-client-issues#8
@nabil1440

Copy link
Copy Markdown
Contributor Author

Closed by a team decision.

  • FlyWP supports the helper plugin and magic login on a Bedrock site that uses
    flywp/bedrock-starter.
  • A site that uses a different repository does not get these features from FlyWP.
  • This work exists to give those features to sites that use a different repository. The decision
    removes the reason for it.

The branch stays. Re-open this if the decision changes.

@nabil1440 nabil1440 closed this Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant