SiteShift

One-click WordPress admin login without passwords: how the mu-plugin works

· 4 min read · by Lennart de Ridder

Twenty local sites means twenty WordPress admin accounts, and you chose none of the passwords. Half came with a pulled production site (whose passwords you shouldn’t know), the other half were generated during an install and pasted into a form you closed. SiteShift’s answer is a login link that works once: click it, you’re in wp-admin, and there is no password to know. This is how it works, why it lives in mu-plugins, and why it must never leave a local site.

The flow

  1. On the site page in SiteShift, the WordPress users are listed by role. You click Log in next to one.
  2. SiteShift generates a random 128-bit token and writes a tiny must-use plugin into the site — wp-content/mu-plugins/siteshift-autologin.php — with that token and the chosen username baked in. Then it opens http://<slug>.localhost:<port>/wp-login.php?siteshift_token=… in your browser.
  3. On that request the mu-plugin runs early on init, compares the query token with the one it was written with, looks the user up by login, calls wp_set_auth_cookie(), deletes its own file, and redirects to /wp-admin/.

That’s the whole thing. No password is read, changed or reset. The user’s real password — the one they use on production, if this is a pulled site — is untouched. The plugin is about twenty lines; here is the part that matters:

add_action('init', function () {
    if (!isset($_GET['siteshift_token']) || $_GET['siteshift_token'] !== '<token>') {
        return;
    }
    $user = get_user_by('login', '<username>');
    wp_set_auth_cookie($user->ID, true);
    @unlink(__FILE__);          // single use: the file removes itself
    wp_safe_redirect(admin_url());
    exit;
}, 1);

Why a must-use plugin

Regular plugins can be deactivated, and on a pulled site the plugin list is whatever the client had. A file in wp-content/mu-plugins/ loads on every request, before regular plugins, and can’t be switched off from wp-admin. That’s exactly the property a login helper needs: it has to work even on a site whose plugins are half broken, which is often the reason you’re logging in.

Writing the file fresh on every click, rather than installing a permanent helper, has a second benefit: when no login is pending there is nothing in mu-plugins at all. The mechanism exists for the seconds between the click and the redirect.

What makes it safe — locally

The token is 16 random bytes from random_bytes(), so it’s not guessable. It’s single-use because the file that knows it deletes itself on success. There’s no shared secret between SiteShift and WordPress to replay, and no password is stored anywhere. What it deliberately does not have is a timer: an unused link stays valid until it’s used or until the next click overwrites the file. On a machine only you can reach, that’s an acceptable trade for simplicity.

Because that’s the real safety property, and it’s simpler than any of the above: the site is only reachable from your own machine. <slug>.localhost resolves to 127.0.0.1 and the PHP server binds there. Nobody else can request the URL, so nobody else can use the token.

Why it must never go to production

Everything above changes the moment the site is on a public host. A login-by-URL file on a reachable server is a live credential sitting in the webroot — the exact words SiteShift’s own source uses for it. The safe design is not “make the token stronger”; it’s “don’t have the file on the server at all”.

So the push excludes it. SiteShift keeps one list of files that must never reach a customer’s server — wp-config.php, the auto-login mu-plugin, and a local-only compatibility shim — and that list feeds both the pre-push diff (so the file is never even offered) and tar’s exclusions (so it can’t slip through if it were). Two places, one list, because when they were two lists they drifted. If you deploy with something else, put wp-content/mu-plugins/siteshift-*.php in that tool’s exclusions too.

If you ever find a login-by-token plugin on a live site — yours or a client’s — remove it first and ask questions later. Convenience plugins from local tools have a way of travelling with a zip-based migration.

The alternatives, for completeness

wp user update admin --user_pass=… resets a password you then have to remember; on a pulled site it also diverges from production, which bites when you push the database back. The community wp login package creates magic links too and is a fine choice if you live in the terminal; SiteShift’s version is the same idea with a button in front of it and the “local only” rule enforced by the push.

L
Lennart de Ridder

Builds SiteShift and runs DeveloKey, a WordPress agency in Leiden. Every guide here comes from running client sites through the same tool.

Local WordPress with bundled PHP and MySQL, pushed to any host over SSH.

Get SiteShift — €9/mo