[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.
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.
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.
|
|
||
| await php.writeFile( | ||
| '/internal/shared/mu-plugins/1-auto-login.php', | ||
| autoLoginMuPlugin |
There was a problem hiding this comment.
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.
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.
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 <berislav.grgicak@gmail.com>
#719) * Update blueprint path to pull from main branch instead of a deleted feature branch. * Password is deprecated and unnecessary. @link WordPress/wordpress-playground#1856 * May as well start them out at the right section as well.
…… (#719) * Update blueprint path to pull from main branch instead of a deleted feature branch. * Password is deprecated and unnecessary. @link WordPress/wordpress-playground#1856 * May as well start them out at the right section as well.
This PR was originally implemented in this branch
Fixes #1706
Motivation for the change, related issues
Handles auto login, e.g. in the
loginBlueprint step, using a platform-provided mu-plugin. This enables using theloginstep across all Playground runtimes without any of the issues with the previous implementation.Before this PR, the
loginworked by making HTTP requests to the/wp-login.phpendpoint. 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_USERconstantUsed by the
loginBlueprint step does.When the
PLAYGROUND_AUTO_LOGIN_AS_USERconstant 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_happenedcookie 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_userGET parameterUsed by the "login" button in various Playground runtimes.
When the
playground_force_auto_login_as_userGET 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=admintriggers a redirect to add the trailing slash, as in/?playground_force_auto_login_as_user=admin/. Let's track that separately.