Three faults, all on the same screen, all only visible once passwords were actually turned off — which until now nobody had done on a live instance. wp-login.php runs wp_signon() on its way to drawing the form, even for a plain GET. Core tolerates that by discarding the result, but only when the error codes are exactly the pair its own password filters produce. Removing those filters is the whole point of turning passwords off, so what was left behind was the generic authentication_failed — printed, in red, above a form with no username and no password, on a site that has neither. Every visitor was told their sign-in had failed before they tried. The paste-a-signature path had no way to submit. It borrowed core's login button, and the stylesheet that retires the password form hid that button too. The one route for people whose keys live on another machine — sign in Electron Cash, paste the result — was therefore broken exactly on the sites most committed to not having passwords. It now carries its own plain submit button, so it also works on the screens where there is no core login form to borrow from, and with JavaScript off. And the username field outlived the password field, although authenticate() never reads it either. "Username or Email Address" sat at the top of a wallet login form: the one thing this fork exists to remove, in the first place anyone looks. Both go now, with their required attributes cleared, because a hidden required field does not fail quietly — it refuses the submit and points an error bubble at a control nobody can see.
75 lines
2.4 KiB
PHP
75 lines
2.4 KiB
PHP
<?php
|
|
/**
|
|
* Plugin Name: Sirius Press Auth
|
|
* Plugin URI: https://code.silentmode.st/silentmode/sirius-press
|
|
* Description: Sign in by signing a challenge with a Bitcoin Cash wallet. Replaces email as the account identity; leaves roles, capabilities and sessions exactly as WordPress made them.
|
|
* Version: 0.1.0
|
|
* Requires at least: 6.5
|
|
* Requires PHP: 7.4
|
|
* Requires Plugins: sirius-press-core
|
|
* Author: Silent Mode
|
|
* Author URI: https://silentmode.st
|
|
* License: GPL-2.0-or-later
|
|
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
|
* Text Domain: sirius-press
|
|
*
|
|
* @package SiriusPress
|
|
*/
|
|
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
define( 'SIRIUS_PRESS_AUTH_VERSION', '0.1.1' );
|
|
define( 'SIRIUS_PRESS_AUTH_DIR', plugin_dir_path( __FILE__ ) );
|
|
define( 'SIRIUS_PRESS_AUTH_URL', plugin_dir_url( __FILE__ ) );
|
|
|
|
add_action(
|
|
'plugins_loaded',
|
|
function () {
|
|
// `Requires Plugins` keeps this from being activated without the core
|
|
// plugin, but an installation can still be mid-upgrade or have core
|
|
// deactivated by hand. Failing with a notice beats a fatal on the
|
|
// login screen, which would lock everyone out of the site.
|
|
if ( ! class_exists( 'SP_Message' ) ) {
|
|
add_action(
|
|
'admin_notices',
|
|
function () {
|
|
printf(
|
|
'<div class="notice notice-error"><p>%s</p></div>',
|
|
esc_html__( 'Sirius Press Auth needs Sirius Press Core to be active. Wallet sign-in is off until it is.', 'sirius-press' )
|
|
);
|
|
}
|
|
);
|
|
return;
|
|
}
|
|
|
|
foreach ( array( 'challenge', 'login', 'register', 'recovery', 'rest', 'profile', 'settings' ) as $part ) {
|
|
require_once SIRIUS_PRESS_AUTH_DIR . 'includes/class-spa-' . $part . '.php';
|
|
}
|
|
|
|
SPA_Login::hooks();
|
|
SPA_Register::hooks();
|
|
SPA_Recovery::hooks();
|
|
SPA_REST::hooks();
|
|
SPA_Profile::hooks();
|
|
SPA_Settings::hooks();
|
|
},
|
|
5
|
|
);
|
|
|
|
/**
|
|
* Ask the current user to re-prove their key before something irreversible.
|
|
*
|
|
* Intended for other plugins: hand it a purpose string and it returns the
|
|
* challenge to render; verify the answer with the `/sirius-press/v1/confirm`
|
|
* endpoint. Exposed as a plain function so a plugin does not have to know
|
|
* this fork's class names to use it.
|
|
*
|
|
* @return array{nonce:string,message:string}
|
|
*/
|
|
function sirius_press_confirmation_challenge() {
|
|
$nonce = SPA_Challenge::issue();
|
|
return array(
|
|
'nonce' => $nonce,
|
|
'message' => SPA_Challenge::message( $nonce, SPA_Challenge::PURPOSE_CONFIRM ),
|
|
);
|
|
}
|