-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change logged-in user redirect to login_init hook #584
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,26 +96,49 @@ public function init() { | |
} | ||
|
||
/** | ||
* Redirect to a specific connection designated in Settings > Advanced | ||
* Redirect logged-in users from wp-login.php. | ||
* Redirect to Universal Login Page under certain conditions and if the option is turned on. | ||
* | ||
* @return bool | ||
*/ | ||
public function login_auto() { | ||
if ( | ||
// Nothing to do. | ||
( ! $this->a0_options->get( 'auto_login', false ) ) | ||
// Auth0 is not ready to process logins. | ||
|| ! WP_Auth0::ready() | ||
// Do not redirect POST requests. | ||
|| strtolower( $_SERVER['REQUEST_METHOD'] ) !== 'get' | ||
// Do not redirect login page override. | ||
|| isset( $_GET['wle'] ) | ||
// Do not redirect log out action. | ||
|| ( isset( $_GET['action'] ) && 'logout' === $_GET['action'] ) | ||
// Do not redirect Auth0 login processing. | ||
|| null !== $this->query_vars( 'auth0' ) | ||
// Do not redirect if already authenticated. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dealing with this condition in the block added above in this method ☝️ |
||
|| is_user_logged_in() | ||
) { | ||
return; | ||
|
||
// Do not redirect anywhere if this is a logout action. | ||
if ( isset( $_GET['action'] ) && 'logout' === $_GET['action'] ) { | ||
return false; | ||
} | ||
|
||
// Do not redirect login page override. | ||
if ( isset( $_GET['wle'] ) ) { | ||
return false; | ||
} | ||
|
||
// Do not redirect non-GET requests. | ||
if ( strtolower( $_SERVER['REQUEST_METHOD'] ) !== 'get' ) { | ||
return false; | ||
} | ||
|
||
// Do not redirect Auth0 login processing. | ||
// TODO: This should be removed as this page is no longer used for callbacks. | ||
if ( null !== $this->query_vars( 'auth0' ) ) { | ||
return false; | ||
} | ||
|
||
// If the user has a WP session, determine where they should end up and redirect. | ||
if ( is_user_logged_in() ) { | ||
$login_redirect = empty( $_REQUEST['redirect_to'] ) ? | ||
$this->a0_options->get( 'default_login_redirection' ) : | ||
filter_var( $_REQUEST['redirect_to'], FILTER_SANITIZE_URL ); | ||
|
||
// Add a cache buster to avoid an infinite redirect loop on pages that check for auth. | ||
$login_redirect = add_query_arg( time(), '', $login_redirect ); | ||
wp_safe_redirect( $login_redirect ); | ||
exit; | ||
} | ||
|
||
// Do not use the ULP if the setting is off or if the plugin is not configured. | ||
if ( ! $this->a0_options->get( 'auto_login', false ) || ! WP_Auth0::ready() ) { | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is used in a hook call so return value is never used ... except in tests now! |
||
} | ||
|
||
$connection = apply_filters( 'auth0_get_auto_login_connection', $this->a0_options->get( 'auto_login_method' ) ); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,50 @@ | |
*/ | ||
class TestLoginManager extends TestCase { | ||
|
||
use setUpTestDb; | ||
use OptionsHelpers; | ||
|
||
use RedirectHelpers; | ||
|
||
use SetUpTestDb; | ||
|
||
use UsersHelper; | ||
|
||
/** | ||
* WP_Auth0_ErrorLog instance. | ||
* | ||
* @var WP_Auth0_ErrorLog | ||
*/ | ||
protected static $error_log; | ||
|
||
/** | ||
* WP_Auth0_UsersRepo instance. | ||
* | ||
* @var WP_Auth0_UsersRepo | ||
*/ | ||
protected static $users_repo; | ||
|
||
/** | ||
* Setup for entire test class. | ||
*/ | ||
public static function setUpBeforeClass() { | ||
parent::setUpBeforeClass(); | ||
self::$opts = WP_Auth0_Options::Instance(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is done once, but its contents are changed multiple times in different tests. I think it should be moved into a method that runs "before each test" so you can ensure the tests are fully independent of each other. e.g. some tests set the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Totally agree but keep in mind that we always have a "state," which is the database and that's where these are stored. A new options object pulls from the test DB so it needs to be explicitly reset each time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also ... |
||
self::$users_repo = new WP_Auth0_UsersRepo( self::$opts ); | ||
self::$error_log = new WP_Auth0_ErrorLog(); | ||
} | ||
|
||
/** | ||
* Run after each test. | ||
*/ | ||
public function tearDown() { | ||
parent::tearDown(); | ||
self::auth0Ready( false ); | ||
$this->stopRedirectHalting(); | ||
self::$error_log->clear(); | ||
self::$opts->set( 'custom_domain', '' ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems easier to throw this instance and create a new one than be changing manually each prop, as you could be forgetting some of them when adding new tests. Note this are tests and performance hit is not relevant here. Instantiate whatever you need the times you need 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree. There are a number of setUp/tearDown things that can/should happen always. Plan is to have a super class that extends the test suite to handle everything that should be done in between. I'm logging your suggestion here and the others I have so it gets handled. |
||
self::$opts->set( 'auth0_implicit_workflow', false ); | ||
self::$opts->set( 'auto_login', 0 ); | ||
} | ||
|
||
/** | ||
* Test that the default auth scopes are returned and filtered properly. | ||
|
@@ -54,13 +97,12 @@ public function testAuthorizeParams() { | |
$auth_params = WP_Auth0_LoginManager::get_authorize_params( $test_connection ); | ||
$this->assertEquals( $test_connection, $auth_params['connection'] ); | ||
|
||
$options = WP_Auth0_Options::Instance(); | ||
$options->set( 'client_id', $test_client_id ); | ||
self::$opts->set( 'client_id', $test_client_id ); | ||
|
||
$auth_params = WP_Auth0_LoginManager::get_authorize_params(); | ||
$this->assertEquals( $test_client_id, $auth_params['client_id'] ); | ||
|
||
$options->set( 'auth0_implicit_workflow', 1 ); | ||
self::$opts->set( 'auth0_implicit_workflow', 1 ); | ||
$auth_params = WP_Auth0_LoginManager::get_authorize_params(); | ||
$this->assertEquals( add_query_arg( 'auth0', 'implicit', site_url( 'index.php' ) ), $auth_params['redirect_uri'] ); | ||
$this->assertEquals( 'id_token', $auth_params['response_type'] ); | ||
|
@@ -85,17 +127,15 @@ function( $params, $connection, $redirect_to ) { | |
* Test that the authorize URL is built properly. | ||
*/ | ||
public function testBuildAuthorizeUrl() { | ||
$options = WP_Auth0_Options::Instance(); | ||
|
||
// Basic authorize URL. | ||
$options->set( 'domain', 'test.auth0.com' ); | ||
$options->set( 'custom_domain', '' ); | ||
self::$opts->set( 'domain', 'test.auth0.com' ); | ||
$auth_url = WP_Auth0_LoginManager::build_authorize_url(); | ||
|
||
$this->assertEquals( 'https://test.auth0.com/authorize', $auth_url ); | ||
|
||
// Custom domain authorize URL. | ||
$options->set( 'custom_domain', 'test-custom.auth0.com' ); | ||
self::$opts->set( 'custom_domain', 'test-custom.auth0.com' ); | ||
$auth_url = WP_Auth0_LoginManager::build_authorize_url(); | ||
|
||
$this->assertEquals( 'https://test-custom.auth0.com/authorize', $auth_url ); | ||
|
@@ -133,4 +173,194 @@ function ( $auth_url, $params ) { | |
); | ||
$this->assertEquals( 'https://test-custom.auth0.com/authorize?test=this', $auth_url ); | ||
} | ||
|
||
/** | ||
* Test that logged-in users are redirected from the wp-login.php page. | ||
*/ | ||
public function testThatLoggedInUserIsRedirectedFromWpLogin() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved from |
||
$this->startRedirectHalting(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what I didn't fully understand from yesterday's response. Couldn't you call this line at the very end of the "run before each test" method? It's cleaner than having to copy-paste it on every test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cleaner but not needed for every test. Some of these cannot be combined because they throw exceptions at different places. |
||
|
||
$login_manager = new WP_Auth0_LoginManager( self::$users_repo, self::$opts ); | ||
|
||
// Configure Auth0. | ||
self::auth0Ready(); | ||
$this->assertTrue( WP_Auth0::ready() ); | ||
|
||
// Set the current user to admin. | ||
$this->setGlobalUser(); | ||
|
||
// Use the default login redirection. | ||
$caught_redirect = [ | ||
'location' => null, | ||
'status' => null, | ||
]; | ||
try { | ||
$login_manager->login_auto(); | ||
} catch ( Exception $e ) { | ||
$caught_redirect = unserialize( $e->getMessage() ); | ||
} | ||
|
||
// Redirect will have a dynamic cache breaker so cannot assertEquals here. | ||
$this->assertNotFalse( strpos( $caught_redirect['location'], 'http://example.org?' ) ); | ||
$this->assertEquals( 302, $caught_redirect['status'] ); | ||
|
||
// Set a one-time login redirect URL. | ||
$_REQUEST['redirect_to'] = 'http://example.org/custom'; | ||
|
||
// Use the default login redirection. | ||
$caught_redirect = [ | ||
'location' => null, | ||
'status' => null, | ||
]; | ||
try { | ||
$login_manager->login_auto(); | ||
} catch ( Exception $e ) { | ||
$caught_redirect = unserialize( $e->getMessage() ); | ||
} | ||
|
||
// Redirect will have a dynamic cache breaker so cannot assertEquals here. | ||
$this->assertNotFalse( strpos( $caught_redirect['location'], 'http://example.org/custom?' ) ); | ||
$this->assertEquals( 302, $caught_redirect['status'] ); | ||
} | ||
|
||
/** | ||
* Test that the ULP redirect happens. | ||
*/ | ||
public function testUlpRedirect() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Set everything up to make sure the ULP redirect happens under normal conditions. |
||
$this->startRedirectHalting(); | ||
|
||
$login_manager = new WP_Auth0_LoginManager( self::$users_repo, self::$opts ); | ||
$this->assertFalse( $login_manager->login_auto() ); | ||
|
||
// Activate settings that result in a ULP redirect. | ||
self::$opts->set( 'auto_login', 1 ); | ||
self::auth0Ready( true ); | ||
self::$opts->set( 'domain', 'test-wp.auth0.com' ); | ||
$this->assertTrue( WP_Auth0::ready() ); | ||
|
||
$caught_redirect = [ | ||
'location' => null, | ||
'status' => null, | ||
]; | ||
try { | ||
// Need to hide error messages here because a cookie is set. | ||
// phpcs:ignore | ||
@$login_manager->login_auto(); | ||
} catch ( Exception $e ) { | ||
$caught_redirect = unserialize( $e->getMessage() ); | ||
} | ||
|
||
$this->assertNotFalse( strpos( $caught_redirect['location'], 'https://test-wp.auth0.com/authorize?' ) ); | ||
$this->assertEquals( 302, $caught_redirect['status'] ); | ||
} | ||
|
||
/** | ||
* Test that the ULP redirect does not happen for non-GET methods. | ||
*/ | ||
public function testThatUlpRedirectIsSkippedForNonGetMethod() { | ||
$this->startRedirectHalting(); | ||
|
||
$login_manager = new WP_Auth0_LoginManager( self::$users_repo, self::$opts ); | ||
|
||
// First, check that a redirect is happening. | ||
self::$opts->set( 'auto_login', 1 ); | ||
self::auth0Ready( true ); | ||
$caught_redirect = []; | ||
try { | ||
// Need to hide error messages here because a cookie is set. | ||
// phpcs:ignore | ||
@$login_manager->login_auto(); | ||
} catch ( Exception $e ) { | ||
$caught_redirect = unserialize( $e->getMessage() ); | ||
} | ||
$this->assertEquals( 302, $caught_redirect['status'] ); | ||
|
||
// Test that request method will stop redirect. | ||
$_SERVER['REQUEST_METHOD'] = 'POST'; | ||
$this->assertFalse( $login_manager->login_auto() ); | ||
|
||
$_SERVER['REQUEST_METHOD'] = 'PATCH'; | ||
$this->assertFalse( $login_manager->login_auto() ); | ||
} | ||
|
||
/** | ||
* Test that the ULP redirect does not happen if we're loading the WP login form. | ||
*/ | ||
public function testThatUlpRedirectIsSkippedForWleOverride() { | ||
$this->startRedirectHalting(); | ||
|
||
$login_manager = new WP_Auth0_LoginManager( self::$users_repo, self::$opts ); | ||
$this->assertFalse( $login_manager->login_auto() ); | ||
|
||
// First, check that a redirect is happening. | ||
self::$opts->set( 'auto_login', 1 ); | ||
self::auth0Ready( true ); | ||
$caught_redirect = []; | ||
try { | ||
// Need to hide error messages here because a cookie is set. | ||
// phpcs:ignore | ||
@$login_manager->login_auto(); | ||
} catch ( Exception $e ) { | ||
$caught_redirect = unserialize( $e->getMessage() ); | ||
} | ||
$this->assertEquals( 302, $caught_redirect['status'] ); | ||
|
||
// Test that WP login override will skip the redirect. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All these 3 checks below should be moved into 3 different tests as the condition for the test changes. |
||
$_GET['wle'] = 1; | ||
$this->assertFalse( $login_manager->login_auto() ); | ||
} | ||
|
||
/** | ||
* Test that the ULP redirect does not happen is this is a logout action. | ||
*/ | ||
public function testThatUlpRedirectIsSkippedForLogout() { | ||
$this->startRedirectHalting(); | ||
|
||
$login_manager = new WP_Auth0_LoginManager( self::$users_repo, self::$opts ); | ||
$this->assertFalse( $login_manager->login_auto() ); | ||
|
||
// First, check that a redirect is happening. | ||
self::$opts->set( 'auto_login', 1 ); | ||
self::auth0Ready( true ); | ||
$caught_redirect = []; | ||
try { | ||
// Need to hide error messages here because a cookie is set. | ||
// phpcs:ignore | ||
@$login_manager->login_auto(); | ||
} catch ( Exception $e ) { | ||
$caught_redirect = unserialize( $e->getMessage() ); | ||
} | ||
$this->assertEquals( 302, $caught_redirect['status'] ); | ||
|
||
// Test that logout will skip the redirect. | ||
$_GET['action'] = 'logout'; | ||
$this->assertFalse( $login_manager->login_auto() ); | ||
} | ||
|
||
/** | ||
* Test that the ULP redirect does not happen if wp-login.php is used as a callback. | ||
*/ | ||
public function testThatUlpRedirectIsSkippedForCallback() { | ||
$this->startRedirectHalting(); | ||
|
||
$login_manager = new WP_Auth0_LoginManager( self::$users_repo, self::$opts ); | ||
$this->assertFalse( $login_manager->login_auto() ); | ||
|
||
// First, check that a redirect is happening. | ||
self::$opts->set( 'auto_login', 1 ); | ||
self::auth0Ready( true ); | ||
$caught_redirect = []; | ||
try { | ||
// Need to hide error messages here because a cookie is set. | ||
// phpcs:ignore | ||
@$login_manager->login_auto(); | ||
} catch ( Exception $e ) { | ||
$caught_redirect = unserialize( $e->getMessage() ); | ||
} | ||
$this->assertEquals( 302, $caught_redirect['status'] ); | ||
|
||
// Test that the auth0 URL param will skip the redirect. | ||
$_REQUEST['auth0'] = 1; | ||
$this->assertFalse( $login_manager->login_auto() ); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meat of the PR here. This still was not early enough to precede any HTML output, leading to a PHP warning.