diff --git a/UPGRADING.md b/UPGRADING.md index ca4969a0..24f4ba43 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -16,7 +16,9 @@ Check that your environment is compatible with 6.0's requirements before upgradi Update your customizations, if necessary: -- **No changes are required for the plugin's built-in features.** Login, logout, the callback handler, and user session handling continue to work as they did in 5.x. The settings stored in the WordPress admin are unchanged. +- **No changes are required for the plugin's built-in features.** Login, logout, the callback handler, and user session handling continue to work as they did in 5.x. The settings stored in the WordPress admin are unchanged. See the authentication error behavior change below. + +- **Authentication errors now show an error page instead of silently redirecting to the homepage.** In 5.x, when Auth0 returned a login error on the callback (`?error=access_denied`, blocked account, breached-password policy, Login Action denial, etc.) or the OAuth token exchange threw an exception, the plugin redirected silently to `/` with no message shown. In 6.x, both paths render a generic error page via `wp_die()`. If your site needs to restore the silent redirect or show a custom message, hook into `auth0_login_failed` (for login errors) or remove and replace the default `auth0_token_exchange_failed` handler. - **User Sync now retries a failed event instead of always discarding it.** In 5.x a sync event that failed at the Management API was dropped from the queue regardless of the reason. In 6.x, a transient failure (an HTTP 429 rate limit, a 5xx server error, or a network error) keeps the event in the queue so the next cron pass retries it. Permanent failures (such as an HTTP 400 from an invalid profile) are still dropped, since retrying them would never succeed. No configuration change is needed, but a queue that previously drained to empty on every pass may now hold a retrying event until it succeeds. - **Custom code that calls the Management API has changed.** In v9 the old `wpAuth0()->getSdk()->management()` entry point is non-functional and will throw a `TypeError`. Use the new `wpAuth0()->getManagement()` accessor instead. It builds a Management client from the Domain, Client ID, and Client Secret you already configure in the plugin settings, and fetches and caches a client credentials token for you automatically. diff --git a/src/Actions/Authentication.php b/src/Actions/Authentication.php index 095419c7..a797e8ec 100644 --- a/src/Actions/Authentication.php +++ b/src/Actions/Authentication.php @@ -41,6 +41,7 @@ final class Authentication extends Base 'login_form_logout' => 'onLogout', 'auth0_logout' => 'onLogout', + 'auth0_login_failed' => ['onLoginFailed', 2, 20], 'auth0_token_exchange_failed' => 'onExchangeFailed', 'before_signup_header' => 'onRegistration', @@ -482,10 +483,13 @@ public function onLogin(): void $state = $this->getSdk()->getRequestParameter('state'); $exchangeParameters = null !== $code && null !== $state; - // Check if authentication flow error parameter is present (?error) + // Check if authentication flow error parameters are present (?error, ?error_description) $error = $this->getSdk() ->getRequestParameter('error'); + $errorDescription = $this->getSdk() + ->getRequestParameter('error_description'); + // Are token exchange parameters present? if ($exchangeParameters) { try { @@ -556,8 +560,9 @@ public function onLogin(): void } if (null !== $error) { - wp_redirect(get_site_url()); - exit; + error_log('Auth0 login error: ' . str_replace(["\r", "\n"], ' ', $error) . ' - ' . str_replace(["\r", "\n"], ' ', $errorDescription ?? '')); + do_action('auth0_login_failed', $error, $errorDescription ?? ''); + return; } if ($exchangeParameters && null === $error && (0 !== wp_get_current_user()->ID || null !== $this->getSdk()->getCredentials())) { @@ -584,11 +589,14 @@ public function onLogin(): void exit; } - public function onExchangeFailed(Throwable $_) + public function onLoginFailed(string $_error, string $_errorDescription): void { - // Custom hook ('auth0_token_exchange_failed') to register when token exchange fails. - wp_redirect(get_site_url()); - exit; + wp_die('There was a problem signing in.', 'Login Error', ['response' => 200]); + } + + public function onExchangeFailed(Throwable $_): void + { + wp_die('There was a problem completing your sign in.', 'Login Error', ['response' => 200]); } public function onLogout(): never diff --git a/src/Actions/Base.php b/src/Actions/Base.php index b2aa7997..bbde4522 100644 --- a/src/Actions/Base.php +++ b/src/Actions/Base.php @@ -30,6 +30,7 @@ final public function addAction(string $event, $method = null): ?Hooks $callback = null; $method ??= $this->registry[$event] ?? null; $arguments = 1; + $priority = $this->getPriority($event); if (null !== $method) { if (is_string($method)) { @@ -39,11 +40,14 @@ final public function addAction(string $event, $method = null): ?Hooks if (is_array($method) && count($method) >= 1 && is_string($method[0]) && is_numeric($method[1])) { $callback = $method[0]; $arguments = (int) $method[1]; + if (isset($method[2]) && is_numeric($method[2])) { + $priority = (int) $method[2]; + } } if (null !== $callback) { return $this->plugin->actions() - ->add($event, $this, $callback, $this->getPriority($event), $arguments); + ->add($event, $this, $callback, $priority, $arguments); } } @@ -106,6 +110,7 @@ final public function removeAction(string $event, $method = null): ?Hooks $callback = null; $method ??= $this->registry[$event] ?? null; $arguments = 1; + $priority = $this->getPriority($event); if (null !== $method) { if (is_string($method)) { @@ -115,11 +120,14 @@ final public function removeAction(string $event, $method = null): ?Hooks if (is_array($method) && count($method) >= 1 && is_string($method[0]) && is_numeric($method[1])) { $callback = $method[0]; $arguments = (int) $method[1]; + if (isset($method[2]) && is_numeric($method[2])) { + $priority = (int) $method[2]; + } } if (null !== $callback) { return $this->plugin->actions() - ->remove($event, $this, $callback, $this->getPriority($event), $arguments); + ->remove($event, $this, $callback, $priority, $arguments); } }