-
Notifications
You must be signed in to change notification settings - Fork 275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Blueprints] Login step – handle passwordless autologin via a PHP mu-plugin #1856
Conversation
* Under the hood, this function submits the [`wp-login.php`](https://developer.wordpress.org/reference/files/wp-login.php/) [form](https://developer.wordpress.org/reference/functions/wp_login_form/) | ||
* just like a user would. | ||
* Under the hood, this function sets the `PLAYGROUND_AUTO_LOGIN_AS_USER` constant. | ||
* The `auto_login.php` mu-plugin uses that constant to log in the user on the first load. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also document where does the auto_login.php
mu-plugin live – it's not bundled with steps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's updated now and mentiones the plugin is located in and loaded by the @wp-playground/wordpress
package.
I didn't include the exact path as it's easy to locate in a editor, but the mention should make it clear that this feature depends on @wp-playground/wordpress
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few nitpicks and otherwise this looks great. Thank you @bgrgicak!
@@ -48,6 +50,11 @@ export async function setupPlatformLevelMuPlugins(php: UniversalPHP) { | |||
` | |||
); | |||
|
|||
await php.writeFile( | |||
'/internal/shared/mu-plugins/1-auto-login.php', | |||
autoLoginMuPlugin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this mu-plugin intended for use as broader platform feature? If not, could this mu-plugin be maintained and written as part of the login
Blueprint step?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this mu-plugin intended for use as broader platform feature? I
Yes, it seems like the only way of supporting auto login in CLI, Studio, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this mu-plugin intended for use as broader platform feature? I
Yes, it seems like the only way of supporting auto login in CLI, Studio, etc.
Ah, thanks for explaining!
This is such a nice change. Thanks for working on it, @bgrgicak! |
…php in index.ts instead of using import ?raw (#1869) Fixes [the failing WordPress Major and Beta update workflow](#1868). It crashed on import "auto_login.php?raw" so this PR removes the import and inlines the php script in a JavaScript variable ## Motivation for the change, related issues We've introduced a bug in #1856 by adding [a `raw` import to the `@wp-playground/wordpress` package](https://github.com/WordPress/wordpress-playground/pull/1856/files#diff-8afd615c3847003caebf2b35102f3a2a107ad9647e095495ecc9302862802191R7). Raw imports aren't native to JavaScript, they are processed on build, using Vite in our case. This is why raw imports work well in our Remote package, but not in the CLI. When Playground is started using Node, the [CLI tries getting the raw text from `auto_login.php`](https://github.com/WordPress/wordpress-playground/pull/1856/files#diff-8afd615c3847003caebf2b35102f3a2a107ad9647e095495ecc9302862802191R7). Instead of getting the text, it gets the path to the imported file (e.g. `/Users/me/Projects/wordpress-playground/packages/playground/wordpress/src/mu-plugins/auto_login.php`). This path is written into the `1-auto-login.php` mu-plugin as a string. When Playground tries to boot, it [checks if WordPress is installed](https://github.com/WordPress/wordpress-playground/blob/ccadc7d0daedda0b59b571e12aade32cf3abaeab/packages/playground/wordpress/src/boot.ts#L243). The expected result of that check is `1`, but because `1-auto-login.php` contains the path as a string, and because WordPress uses PHP `include` to load that file, the path gets written to stdout and mixed with the script output. The outcome is that `result.text` is `/Users/me/Projects/wordpress-playground/packages/playground/wordpress/src/mu-plugins/auto_login.php1` instead of `1`. ## Implementation details This PR moves the auto-login code from a PHP file to inline code. The approach matches what we did with other `mu-plugins` that must be loaded both in the CLI and on the web. TODO: - [Add tests to ensure the CLI works](#1871) - Consider adding instructions for setting up the CLI as a global package ## Testing Instructions (or ideally a Blueprint) - Run `bun packages/playground/wordpress-builds/build/build.js --wp-version=latest-minus-1 --output-js=packages/playground/wordpress-builds/src/wordpress --output-assets=packages/playground/wordpress-builds/public` - Confirm it works
This PR: * Replaces the `wp_redirect()` call with `header("Location: ")` to ensure support for all valid redirection URLs. * Adds a timeout before probing for the embedded Playground `iframe` URL when the `load` event handler runs. ### Ditching `wp_redirect()` The `wp_redirect()` call was introduced in #1856 to handle the post-autologin redirect. Unfortunately, it strips valid sequences such as `%0A` and `%0D` from the redirection URL. This isn't useful in Playground and breaks valid use-cases such as using the `?url=` parameter to initialize `html-api-debugger` with a valid HTML markup containing newlines. ### Timeout before probing `contentWindow.location.href` When navigating to a page with %0A sequences (encoded newlines) in the query string, the `location.href` property of the iframe's content window doesn't seem to reflect them. Everything else is in place, but not the %0A sequences. Weirdly, these sequences are available after the next event loop tick – hence the `setTimeout(0)`. The exact cause is unclear to me. The WHATWG HTML Standard [1] has a few hints: * Current and active session history entries may get out of sync for iframes. * Documents inside iframes have "is delaying load events" set to true. But there doesn't seem to be any concrete explanation and no recommended remediation. If anyone has a clue, please share it in a GitHub issue or start a new PR. [1] https://html.spec.whatwg.org/multipage/document-sequences.html#nav-active-history-entry ## Testing instructions CI tests aside, try this: 1. Go to http://localhost:5400/website-server/?plugin=html-api-debugger&url=%2Fwp-admin%2Fadmin.php%3Fpage%3Dhtml-api-debugger%26html%3D%253Cdiv%253E%250A1%250A2%250A3%250A%253C%252Fdiv%253E&wp=6.6&php=8.0&networking=no&language=&multisite=no&random=pf3oq1y3vx 2. Confirm the "address bar" on the Playground page reflects the actual, correct URL: `/wp-admin/admin.php?page=html-api-debugger&html=%3Cdiv%3E%0A1%0A2%0A3%0A%3C%2Fdiv%3E` 3. Confirm you can see the following HTML ``` <div> 1 2 3 </div> ``` cc @sirreal @bgrgicak
…ram (#1945) This PR: * Replaces the `wp_redirect()` call with `header("Location: ")` to ensure support for all valid redirection URLs. * Adds a timeout before probing for the embedded Playground `iframe` URL when the `load` event handler runs. ### Ditching `wp_redirect()` The `wp_redirect()` call was introduced in #1856 to handle the post-autologin redirect. Unfortunately, it strips valid sequences such as `%0A` and `%0D` from the redirection URL. This isn't useful in Playground and breaks valid use-cases such as using the `?url=` parameter to initialize `html-api-debugger` with a valid HTML markup containing newlines. ### Timeout before probing `contentWindow.location.href` When navigating to a page with %0A sequences (encoded newlines) in the query string, the `location.href` property of the iframe's content window doesn't seem to reflect them. Everything else is in place, but not the %0A sequences. Weirdly, these sequences are available after the next event loop tick – hence the `setTimeout(0)`. The exact cause is unclear to me. The WHATWG HTML Standard [1] has a few hints: * Current and active session history entries may get out of sync for iframes. * Documents inside iframes have "is delaying load events" set to true. But there doesn't seem to be any concrete explanation and no recommended remediation. If anyone has a clue, please share it in a GitHub issue or start a new PR. [1] https://html.spec.whatwg.org/multipage/document-sequences.html#nav-active-history-entry ## Testing instructions CI tests aside, try this: 1. Go to http://localhost:5400/website-server/?plugin=html-api-debugger&url=%2Fwp-admin%2Fadmin.php%3Fpage%3Dhtml-api-debugger%26html%3D%253Cdiv%253E%250A1%250A2%250A3%250A%253C%252Fdiv%253E&wp=6.7&php=8.0&networking=no&language=&multisite=no&random=pf3oq1y3vx 2. Confirm the "address bar" on the Playground page reflects the actual, correct URL: `/wp-admin/admin.php?page=html-api-debugger&html=%3Cdiv%3E%0A1%0A2%0A3%0A%3C%2Fdiv%3E` 3. Confirm you can see the following HTML ``` <div> 1 2 3 </div> ``` cc @sirreal @bgrgicak --------- Co-authored-by: Bero <[email protected]>
This PR was originally implemented in this branch
Fixes #1706
Motivation for the change, related issues
Handles auto login, e.g. in the
login
Blueprint step, using a platform-provided mu-plugin. This enables using thelogin
step across all Playground runtimes without any of the issues with the previous implementation.Before this PR, the
login
worked by making HTTP requests to the/wp-login.php
endpoint. That approach had significant downsides:Implementation details
To fix it and make the login step more robust login now uses a login PHP file that logs in the user with their credentials.
The new script only requires a username, the password is now deprecated.
There are two ways to trigger the auto-login:
The
PLAYGROUND_AUTO_LOGIN_AS_USER
constantUsed by the
login
Blueprint step does.When the
PLAYGROUND_AUTO_LOGIN_AS_USER
constant is defined, this mu-pluginwill automatically log the user in on their first visit. The username is
the value of the constant.
On subsequent visits, the
playground_auto_login_happened
cookie will bedetected and the user will not be logged in. This means the "logout" feature
will work as expected.
The
playground_force_auto_login_as_user
GET parameterUsed by the "login" button in various Playground runtimes.
When the
playground_force_auto_login_as_user
GET parameter is present,this mu-plugin will automatically log in any logged out visitor. This will
happen every time they visit, not just on their first visit.
Testing Instructions (or ideally a Blueprint)
/?playground_force_auto_login_as_user=admin&
and confirm you were logged in again.cc @brandonpayton – the
/?playground_force_auto_login_as_user=admin
triggers a redirect to add the trailing slash, as in/?playground_force_auto_login_as_user=admin/
. Let's track that separately.