Repository navigation
feat: Authenticated API requests - #14
Conversation
Provide the editor with context managed by the host application.
Simplify retrieval of configuration values provided by the host app.
Improve performance by reducing local storage read frequency.
Communicate CORS support and avoid incorrect presumptions in third-party responses (e.g., Jetpack adds custom header values).
Improve code comprehension.
`@wordpress/api-fetch` manages this header for us as long as we rely upon the default fetcher. https://github.com/WordPress/gutenberg/blob/5dae25b15e82a59d28c6c065b5a3745f3f83980f/packages/api-fetch/src/index.js#L96-L100
| export function initializeApiFetch() { | ||
| apiFetch.use(apiFetch.createRootURLMiddleware('')); | ||
| const { siteURL, authToken } = getGBKit(); | ||
| const rootURL = siteURL ? `${siteURL}/wp-json/` : undefined; |
There was a problem hiding this comment.
I've just realized that for WordPress.com sites, we'll need to use https://public-api.wordpress.com/ instead. This means we'll need to remove the wp-json path and include it in the siteURL parameter. I suggest we address this in a separate PR, as I encountered some issues with the endpoint paths when attempting to connect to https://public-api.wordpress.com/.
For now this will work perfectly for self-hosted sites.
There was a problem hiding this comment.
Interesting. I make successful requests with this approach for an Atomic WPCOM site. Is the use of https://public-api.wordpress.com/ merely a recommendation and/or potentially required for Simple sites?
There was a problem hiding this comment.
I was trying with a simple site yeah. For Atomic, it's the same as self-hosted using the site's URL, but for Simple sites I think we'll need to go through the WordPress.com API 🤔
I ended up trying this because I checked the editor's Web view source code and for Simple sites, it sets https://public-api.wordpress.com/ for the createRootURLMiddleware middleware and for Atomic, it just uses the site's URL e.g. https://geriuxxtestingbusiness123.wpcomstaging.com/wp-json/
There was a problem hiding this comment.
Makes sense. When we address this, we might consider renaming siteURL to something like siteAPIURL.
geriux
left a comment
There was a problem hiding this comment.
LGTM! I've tested it using the host app and I was able to pass the data successfully. 🚀
Nice work!
…script The trailing `"done";` dates from #14, when the configuration was injected with `evaluateJavaScript`, which needed a serializable trailing expression. #15 moved the script to a document-start `WKUserScript`, whose completion value WebKit discards, and the line has been inert since. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016zAv5Tqtqr1bcYWVDJHGAh
…script The trailing `"done";` dates from #14, when the configuration was injected with `evaluateJavaScript`, which needed a serializable trailing expression. #15 moved the script to a document-start `WKUserScript`, whose completion value WebKit discards, and the line has been inert since. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016zAv5Tqtqr1bcYWVDJHGAh
…script The trailing `"done";` dates from #14, when the configuration was injected with `evaluateJavaScript`, which needed a serializable trailing expression. #15 moved the script to a document-start `WKUserScript`, whose completion value WebKit discards, and the line has been inert since. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016zAv5Tqtqr1bcYWVDJHGAh
…script The trailing `"done";` dates from #14, when the configuration was injected with `evaluateJavaScript`, which needed a serializable trailing expression. #15 moved the script to a document-start `WKUserScript`, whose completion value WebKit discards, and the line has been inert since. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016zAv5Tqtqr1bcYWVDJHGAh
* refactor: read the editor configuration from the injected global only `getGBKit` fell back to a copy of the configuration in `localStorage`. Boot waits for `window.GBKit` before anything reads the configuration, and outside `?dev_mode` aborts when it never arrives, so the fallback could only ever serve a previous session's values to a dev-mode page with no host. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JsMCoa3jNEuvnhxicDVRBV * fix(ios): stop persisting the editor configuration `GBKit` carries the site credential and the local server's port and tokens, all valid only for the load that injected them, and iOS mirrored it into `localStorage`, which the default website data store keeps on disk across launches. The document-start user script replays the global on every navigation, including the reload after a WebContent process termination, so the copy had no reader. Remove the key as the configuration is injected so devices upgraded from an earlier version are scrubbed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JsMCoa3jNEuvnhxicDVRBV * fix(android): stop persisting the editor configuration `GBKit` carries the site credential and the local server's port and token, all valid only for the load that injected them. The view re-injects the global on every page start and wipes web storage before each load, so the `localStorage` copy had no reader and nothing left to clear on detach. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JsMCoa3jNEuvnhxicDVRBV * docs: describe where the local server's token lives The CORS rationale on both platforms named `localStorage` alongside `window.GBKit` as where the editor holds the per-session bearer token. The token now lives in the injected global only. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JsMCoa3jNEuvnhxicDVRBV * docs(android): correct the CORS rationale's origin premise The comment justified `*` partly by claiming the editor loads from file:// (Origin null) and so can't be allowlisted. That holds on iOS, but the Android editor has loaded from the site's own origin since #181, where echoing the origin would be perfectly possible. Name the document, not the origin, as what scopes the token: same-origin site pages exist on Android, and it is the per-document JS global that keeps them from reading it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016zAv5Tqtqr1bcYWVDJHGAh * refactor(ios): drop the dead completion value from the configuration script The trailing `"done";` dates from #14, when the configuration was injected with `evaluateJavaScript`, which needed a serializable trailing expression. #15 moved the script to a document-start `WKUserScript`, whose completion value WebKit discards, and the line has been inert since. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016zAv5Tqtqr1bcYWVDJHGAh * test: cover getGBKit's injected-global-only contract `getGBKit` now ignores any persisted copy, but nothing held that contract in place: the suite only ever exercised it through `window.GBKit`, so restoring the storage fallback would have left every test green. Verified as a tripwire — reinstating the fallback fails the second case. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016zAv5Tqtqr1bcYWVDJHGAh * docs: say when the configuration scrub runs The iOS comment promised that an upgraded device "is scrubbed" without saying this only happens on the next editor load, and left no signal for when the migration can be dropped. Document `clearConfig` as teardown-only: with the storage fallback gone, `window.GBKit` is the editor's only source of configuration, so clearing it under a live editor now leaves that editor unusable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016zAv5Tqtqr1bcYWVDJHGAh * docs: rest the CORS rationale on the token alone Both comments claimed no other document can read the editor's global, which overstated the guarantee and disagreed across platforms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEok5vK3cCWGfcQp8zEGWW --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Enable authenticated API requests to a site URL via the basic authentication
scheme with application passwords.
Testing Instructions
siteURLandauthTokenvalues within theEditorViewControllerconstructor.