From 4675d282a712c3da4efed0cca1fc7fa0c3435551 Mon Sep 17 00:00:00 2001 From: Snehil Kishore Date: Tue, 22 Sep 2026 16:07:58 +0530 Subject: [PATCH 1/3] fix: respect redirect_to parameter after login Closes #962 --- src/Actions/Authentication.php | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Actions/Authentication.php b/src/Actions/Authentication.php index bdb265a3..dc96ae99 100644 --- a/src/Actions/Authentication.php +++ b/src/Actions/Authentication.php @@ -536,7 +536,20 @@ public function onLogin(): void wp_set_current_user($wpUser->ID); wp_set_auth_cookie($wpUser->ID, true); do_action('wp_login', $wpUser->user_login, $wpUser); - wp_redirect('/'); + + $destination = '/'; + + if (null !== $state) { + $transientKey = 'auth0_redirect_' . hash('sha256', $state); + $stored = get_transient($transientKey); + + if (false !== $stored) { + delete_transient($transientKey); + $destination = (string) $stored; + } + } + + wp_redirect($destination); exit; } } @@ -552,7 +565,19 @@ public function onLogin(): void exit; } - wp_redirect($this->getSdk()->login()); + $loginParams = []; + + if (isset($_REQUEST['redirect_to'])) { + $redirectTo = wp_validate_redirect(esc_url_raw($_REQUEST['redirect_to']), ''); + + if ('' !== $redirectTo) { + $stateKey = wp_generate_password(32, false); + set_transient('auth0_redirect_' . hash('sha256', $stateKey), $redirectTo, 10 * MINUTE_IN_SECONDS); + $loginParams['state'] = $stateKey; + } + } + + wp_redirect($this->getSdk()->login(params: $loginParams)); exit; } From f968f02bcc85f5021aae047a131f13e0262444d3 Mon Sep 17 00:00:00 2001 From: Snehil Kishore Date: Tue, 22 Sep 2026 17:00:56 +0530 Subject: [PATCH 2/3] fix: use subsite URL as redirect fallback on Multisite --- src/Actions/Authentication.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Actions/Authentication.php b/src/Actions/Authentication.php index dc96ae99..bdf9b04b 100644 --- a/src/Actions/Authentication.php +++ b/src/Actions/Authentication.php @@ -537,7 +537,7 @@ public function onLogin(): void wp_set_auth_cookie($wpUser->ID, true); do_action('wp_login', $wpUser->user_login, $wpUser); - $destination = '/'; + $destination = get_site_url(); if (null !== $state) { $transientKey = 'auth0_redirect_' . hash('sha256', $state); From 523ea3246edca8f1a507a60c104c58126ac6100b Mon Sep 17 00:00:00 2001 From: Snehil Kishore Date: Thu, 24 Sep 2026 00:07:12 +0530 Subject: [PATCH 3/3] fix: guard redirect_to against array input, clear transient on already-authenticated path - Add is_string() check before esc_url_raw() to prevent a PHP 8 fatal when redirect_to is submitted as an array (redirect_to[]=x) - Delete the redirect transient in the already-authenticated early-return path so it does not linger until TTL expiry - Align the already-authenticated redirect with get_site_url() for Multisite subdirectory installs - Note redirect_to support in README --- README.md | 2 +- src/Actions/Authentication.php | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b8c2ba20..915b0e0c 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ By default, WordPress' task manager runs on every page load, which is inadvisabl ### Authentication with Universal Login -The plugin hands authentication over to Auth0's Universal Login. Visitors sign in through your Auth0 tenant rather than the default WordPress login form, which lets you layer on Auth0 capabilities such as MFA, SSO, Passwordless, and Passkeys without changing your WordPress site. Authentication is turned on with a single "Enable Authentication" toggle once your Domain, Client ID, and Client Secret are configured. +The plugin hands authentication over to Auth0's Universal Login. Visitors sign in through your Auth0 tenant rather than the default WordPress login form, which lets you layer on Auth0 capabilities such as MFA, SSO, Passwordless, and Passkeys without changing your WordPress site. Authentication is turned on with a single "Enable Authentication" toggle once your Domain, Client ID, and Client Secret are configured. After a successful login, the plugin respects WordPress's standard `redirect_to` parameter. If a logged-out user visits a protected page, they are returned to that page after authenticating. ### WordPress user management diff --git a/src/Actions/Authentication.php b/src/Actions/Authentication.php index bdf9b04b..f7db8172 100644 --- a/src/Actions/Authentication.php +++ b/src/Actions/Authentication.php @@ -561,13 +561,16 @@ public function onLogin(): void } if ($exchangeParameters && null === $error && (0 !== wp_get_current_user()->ID || null !== $this->getSdk()->getCredentials())) { - wp_redirect('/'); + if (null !== $state) { + delete_transient('auth0_redirect_' . hash('sha256', $state)); + } + wp_redirect(get_site_url()); exit; } $loginParams = []; - if (isset($_REQUEST['redirect_to'])) { + if (isset($_REQUEST['redirect_to']) && is_string($_REQUEST['redirect_to'])) { $redirectTo = wp_validate_redirect(esc_url_raw($_REQUEST['redirect_to']), ''); if ('' !== $redirectTo) {