Skip to content

Commit

Permalink
Replace token ID check with full token check; improve validation process
Browse files Browse the repository at this point in the history
  • Loading branch information
joshcanhelp committed Dec 13, 2018
1 parent 6701aee commit 3e7d743
Show file tree
Hide file tree
Showing 9 changed files with 410 additions and 151 deletions.
30 changes: 10 additions & 20 deletions lib/WP_Auth0_Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ protected function getAuthorizationHeader() {
protected function migration_ws_login() {

// Migration web service is not turned on.
if ( $this->a0_options->get( 'migration_ws' ) == 0 ) {
if ( ! $this->a0_options->get( 'migration_ws' ) ) {
return $this->error_return_array( 403 );
}

Expand All @@ -170,21 +170,16 @@ protected function migration_ws_login() {
}
}

$authorization = $this->getAuthorizationHeader();
$authorization = trim( str_replace( 'Bearer ', '', $authorization ) );

$secret = $this->a0_options->get_client_secret_as_key( true );
$token_id = $this->a0_options->get( 'migration_token_id' );
$authorization = trim( str_replace( 'Bearer ', '', $this->getAuthorizationHeader() ) );
$migration_token = $this->a0_options->get( 'migration_token' );

try {
if ( empty( $authorization ) ) {
throw new Exception( __( 'Unauthorized: missing authorization header', 'wp-auth0' ), 401 );
}

$token = JWT::decode( $authorization, $secret, array( 'HS256' ) );

if ( $token->jti != $token_id ) {
throw new Exception( __( 'Invalid token ID', 'wp-auth0' ), 401 );
if ( $authorization !== $migration_token ) {
throw new Exception( __( 'Invalid token', 'wp-auth0' ), 401 );
}

if ( empty( $_POST['username'] ) ) {
Expand Down Expand Up @@ -223,7 +218,7 @@ protected function migration_ws_login() {
protected function migration_ws_get_user() {

// Migration web service is not turned on.
if ( $this->a0_options->get( 'migration_ws' ) == 0 ) {
if ( ! $this->a0_options->get( 'migration_ws' ) ) {
return $this->error_return_array( 403 );
}

Expand All @@ -235,11 +230,8 @@ protected function migration_ws_get_user() {
}
}

$authorization = $this->getAuthorizationHeader();
$authorization = trim( str_replace( 'Bearer ', '', $authorization ) );

$secret = $this->a0_options->get_client_secret_as_key( true );
$token_id = $this->a0_options->get( 'migration_token_id' );
$authorization = trim( str_replace( 'Bearer ', '', $this->getAuthorizationHeader() ) );
$migration_token = $this->a0_options->get( 'migration_token' );

$user = null;

Expand All @@ -248,10 +240,8 @@ protected function migration_ws_get_user() {
throw new Exception( __( 'Unauthorized: missing authorization header', 'wp-auth0' ), 401 );
}

$token = JWT::decode( $authorization, $secret, array( 'HS256' ) );

if ( $token->jti != $token_id ) {
throw new Exception( __( 'Invalid token ID', 'wp-auth0' ), 401 );
if ( $authorization !== $migration_token ) {
throw new Exception( __( 'Invalid token', 'wp-auth0' ), 401 );
}

if ( ! isset( $_POST['username'] ) ) {
Expand Down
15 changes: 15 additions & 0 deletions lib/admin/WP_Auth0_Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,22 @@ public function create_account_message() {
);
}

/**
* Output the settings page with a generic settings saved message if none is present.
*/
public function render_settings_page() {
$notifications = get_settings_errors();
$message = __( 'Settings saved.', 'wp-auth0' );
$add_settings_saved = true;
foreach ( $notifications as $notification ) {
if ( $message === $notification['message'] ) {
$add_settings_saved = false;
break;
}
}
if ( $add_settings_saved ) {
add_settings_error( 'wp_auth0_settings', 'wp_auth0_settings', $message, 'updated' );
}
include WPA0_PLUGIN_DIR . 'templates/settings.php';
}
}
99 changes: 44 additions & 55 deletions lib/admin/WP_Auth0_Admin_Advanced.php
Original file line number Diff line number Diff line change
Expand Up @@ -705,63 +705,52 @@ public function basic_validation( $old_options, $input ) {
return $input;
}

public function migration_ws_validation( $old_options, $input ) {
$input['migration_ws'] = ( isset( $input['migration_ws'] ) ? $input['migration_ws'] : 0 );

if ( $old_options['migration_ws'] != $input['migration_ws'] ) {

if ( 1 == $input['migration_ws'] ) {

$token_id = uniqid();
$secret = $input['client_secret'];
if ( $input['client_secret_b64_encoded'] ) {
$secret = JWT::urlsafeB64Decode( $secret );
}

$input['migration_token'] = JWT::encode(
array(
'scope' => 'migration_ws',
'jti' => $token_id,
),
$secret
);
$input['migration_token_id'] = $token_id;

$this->add_validation_error(
__( 'User Migration needs to be configured manually. ', 'wp-auth0' )
. __( 'Please see Advanced > Users Migration below for your token, instructions are ', 'wp-auth0' )
. '<a href="https://auth0.com/docs/users/migrations/automatic">HERE</a>.'
);

} else {
$input['migration_token'] = null;
$input['migration_token_id'] = null;

if ( isset( $old_options['db_connection_id'] ) ) {

$connection = WP_Auth0_Api_Client::get_connection( $input['domain'], $input['auth0_app_token'], $old_options['db_connection_id'] );

$connection->options->enabledDatabaseCustomization = false;
$connection->options->import_mode = false;

$response = WP_Auth0_Api_Client::update_connection( $input['domain'], $input['auth0_app_token'], $old_options['db_connection_id'], $connection );
} else {
$response = false;
}

if ( $response === false ) {
$error = __( 'There was an error disabling your custom database. Check how to do it manually ', 'wp-auth0' );
$error .= '<a href="https://manage.auth0.com/#/connections/database">HERE</a>.';
$this->add_validation_error( $error );
}
}
/**
* Validation for the migration_ws setting.
* Generates new migration tokens if none is present.
*
* @param array $old_options - Option values before savings.
* @param array $input - New option values to validate.
*
* @return array
*/
public function migration_ws_validation( array $old_options, array $input ) {
$input['migration_ws'] = isset( $input['migration_ws'] ) ? $input['migration_ws'] : 0;

$this->router->setup_rewrites( $input['migration_ws'] == 1 );
flush_rewrite_rules();
} else {
$input['migration_token'] = $old_options['migration_token'];
$input['migration_token_id'] = $old_options['migration_token_id'];
// No longer using the token ID for validation.
$input['migration_token_id'] = null;

// No change to migration endpoints, keep old token data.
if ( $old_options['migration_ws'] === $input['migration_ws'] ) {
$input['migration_token'] = $old_options['migration_token'];
return $input;
}

// Migration endpoints turned off; warn admin of implications.
if ( empty( $input['migration_ws'] ) ) {
$input['migration_token'] = null;

$error = __( 'User migration endpoints deactivated. ', 'wp-auth0' );
$error .= __( 'Custom database connections can be deactivated in the ', 'wp-auth0' );
$error .= $this->get_dashboard_link( 'connections/database' );
$this->add_validation_error( $error, 'updated' );
return $input;
}

// If we don't have a token yet, generate one.
if ( empty( $input['migration_token'] ) ) {
$input['migration_token'] = base64_encode( openssl_random_pseudo_bytes( 64 ) );
}

$error = __( 'User migration endpoints activated. ', 'wp-auth0' );
$error .= __( 'The custom database scripts needs to be configured manually as described ', 'wp-auth0' );
$error .= $this->get_docs_link( 'users/migrations/automatic' ) . '. ';
$error .= __( 'Please see Advanced > Users Migration below for the token to use.', 'wp-auth0' );
$this->add_validation_error( $error, 'updated' );

$this->router->setup_rewrites();
flush_rewrite_rules();

return $input;
}

Expand Down
14 changes: 5 additions & 9 deletions lib/admin/WP_Auth0_Admin_Generic.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,13 @@ public function input_validator( $input, $old_options = null ) {
}

/**
* Wrapper for add_settings_error
* Wrapper for add_settings_error to output error message on settings change failure.
*
* @param string $error - translated error message
* @param string $error - Translated error message.
* @param string $type - Notice type, "error" by default or "updated".
*/
protected function add_validation_error( $error ) {
add_settings_error(
$this->_option_name,
$this->_option_name,
$error,
'error'
);
protected function add_validation_error( $error, $type = 'error' ) {
add_settings_error( $this->_option_name, $this->_option_name, $error, $type );
}

protected function rule_validation( $old_options, $input, $key, $rule_name, $rule_script ) {
Expand Down
5 changes: 0 additions & 5 deletions templates/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@
<a target="_blank" href="https://manage.auth0.com/#/clients/<?php echo WP_Auth0_Options::Instance()->get( 'client_id' ); ?>/connections"><?php _e( 'here', 'wp-auth0' ); ?></a>.
</div>

<?php if ( count( get_settings_errors() ) == 0 && isset( $_GET['settings-updated'] ) ) { ?>
<div id="message" class="updated">
<p><strong><?php _e( 'Settings saved.' ); ?></strong></p>
</div>
<?php } ?>
<?php settings_errors(); ?>

<ul class="nav nav-tabs" role="tablist">
Expand Down
123 changes: 123 additions & 0 deletions tests/testAdmin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php
/**
* Contains Class TestAdmin.
*
* @package WP-Auth0
*
* @since 3.9.0
*/

use PHPUnit\Framework\TestCase;

/**
* Class TestAdmin.
*/
class TestAdmin extends TestCase {

use SetUpTestDb {
setUp as setUpDb;
}

/**
* Instance of WP_Auth0_Options.
*
* @var WP_Auth0_Options
*/
public static $opts;

/**
* Instance of WP_Auth0_Admin.
*
* @var WP_Auth0_Admin
*/
public static $admin;

/**
* WP_Auth0_ErrorLog instance.
*
* @var WP_Auth0_ErrorLog
*/
protected static $error_log;

/**
* Default expected success message.
*
* @var string
*/
protected static $default_msg = 'Settings saved.';

/**
* Setup for entire test class.
*/
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
self::$opts = WP_Auth0_Options::Instance();
$router = new WP_Auth0_Routes( self::$opts );
self::$admin = new WP_Auth0_Admin( self::$opts, $router );
self::$error_log = new WP_Auth0_ErrorLog();
}

/**
* Runs after each test method.
*/
public function setUp() {
parent::setUp();
self::setUpDb();
}

/**
* Runs after each test method.
*/
public function tearDown() {
parent::tearDown();
self::$error_log->clear();
}

/**
* Test that a default success message is added if there is not one.
*/
public function testThatSettingsPageRendersWithDefaultNotice() {
ob_start();
self::$admin->render_settings_page();
ob_end_clean();

$notifications = get_settings_errors();

$this->assertCount( 1, $notifications );
$this->assertEquals( self::$default_msg, $notifications[0]['message'] );
}

/**
* Test that a default success message is not added if there is already one.
*/
public function testThatSettingsPageRendersWithoutDefaultNotice() {
add_settings_error( 'wp_auth0_settings', 'wp_auth0_settings', self::$default_msg, 'updated' );

ob_start();
self::$admin->render_settings_page();
ob_end_clean();

$notifications = get_settings_errors();

$this->assertCount( 1, $notifications );
$this->assertEquals( self::$default_msg, $notifications[0]['message'] );
}

/**
* Test that a default success message is added if there is another non-default message present.
*/
public function testThatSettingsPageRendersWithAdditionalNotice() {
$message_1 = __( 'Another message', 'wp-auth0' );
add_settings_error( 'wp_auth0_settings', 'wp_auth0_settings', $message_1, 'updated' );

ob_start();
self::$admin->render_settings_page();
ob_end_clean();

$notifications = get_settings_errors();

$this->assertCount( 2, $notifications );
$this->assertEquals( $message_1, $notifications[0]['message'] );
$this->assertEquals( self::$default_msg, $notifications[1]['message'] );
}
}
Loading

0 comments on commit 3e7d743

Please sign in to comment.