Skip to content
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

Better Management API token handling #632

Merged
merged 6 commits into from
Mar 15, 2019
Merged

Conversation

joshcanhelp
Copy link
Contributor

@joshcanhelp joshcanhelp commented Mar 14, 2019

Changes

  • Remove Management API access token validation
  • Store new API tokens and scope in transients

References

Closes #631

Testing

  • This change adds unit test coverage
  • This change has been tested on the latest version of WP

Checklist

@joshcanhelp joshcanhelp force-pushed the fix-m-api-token-handling branch from 23975e1 to c1b56f6 Compare March 15, 2019 00:20
@auth0 auth0 deleted a comment from codecov-io Mar 15, 2019
@codecov-io
Copy link

codecov-io commented Mar 15, 2019

Codecov Report

Merging #632 into master will increase coverage by 0.13%.
The diff coverage is 100%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master     #632      +/-   ##
============================================
+ Coverage     37.83%   37.96%   +0.13%     
+ Complexity     1243     1240       -3     
============================================
  Files            51       51              
  Lines          3840     3832       -8     
============================================
+ Hits           1453     1455       +2     
+ Misses         2387     2377      -10
Impacted Files Coverage Δ Complexity Δ
lib/profile/WP_Auth0_Profile_Delete_Data.php 100% <ø> (ø) 8 <0> (ø) ⬇️
lib/profile/WP_Auth0_Profile_Delete_Mfa.php 100% <ø> (ø) 12 <0> (ø) ⬇️
lib/api/WP_Auth0_Api_Client_Credentials.php 100% <100%> (ø) 11 <4> (+3) ⬆️
lib/api/WP_Auth0_Api_Abstract.php 100% <100%> (+27.65%) 27 <0> (-6) ⬇️
lib/WP_Auth0_Options.php 73.26% <0%> (-10.9%) 28% <0%> (ø)
lib/WP_Auth0_Api_Client.php 31.7% <0%> (-1.36%) 81% <0%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9bddec6...5a2a230. Read the comment docs.

@joshcanhelp joshcanhelp changed the title Failing tests for revised Client Credentials behavior Better Management API token handling Mar 15, 2019
@joshcanhelp joshcanhelp added this to the 3.10.0 milestone Mar 15, 2019
@joshcanhelp joshcanhelp marked this pull request as ready for review March 15, 2019 17:13
if ( ! $this->api_token ) {
$this->api_token = $this->options->get( 'auth0_app_token' ); // REMOVE
}
$api_token = WP_Auth0_Api_Client_Credentials::get_stored_token();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason to have this method static and the call() one part of the instance instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call() is part of an abstract so it needs to be defined. This can accept parameters required for the API call. In this case, no parameters are needed but other child classes use that.

The static methods don't require any parameters and act on global state (database).

}

// No token to use, error recorded in previous steps.
if ( ! $this->api_token_decoded ) {
wp_cache_delete( self::CACHE_KEY, WPA0_CACHE_GROUP );
if ( ! $api_token ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this case be covered by a exception thrown in call() if the request fails somehow?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No exceptions thrown in call() or else they would have to be caught. It just returns bool whether it worked or not.

return false;
}

if ( WP_Auth0_Api_Client_Credentials::check_stored_scope( $scope ) ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this line doing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checks that the scope we have stored (from the CC grant call) matches the scope we need.

public static function check_stored_scope( $scope ) {
$stored_scope = get_transient( self::SCOPE_TRANSIENT_KEY );
$scopes = explode( ' ', $stored_scope );
return ! empty( $scopes ) && in_array( $scope, $scopes );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this ! empty( $scopes ) is redundant. You're already looking for a match with in_array.
Also I don't see you exploding the $scope parameter. What if the value has multiple scopes separated with spaces? Adding a tests scenario for this will help you fix it

Copy link
Contributor Author

@joshcanhelp joshcanhelp Mar 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this ! empty( $scopes ) is redundant

You're right, explode() always returns an array even if the "string" is null/false. I'll change that.

Also I don't see you exploding the $scope parameter. What if the value has multiple scopes separated with spaces? Adding a tests scenario for this will help you fix it

There is a test for multiple scopes. The $scope parameter only excepts one (we only ever need one for the API call [at least the ones we have currently]). AFAIK, the endpoints never require more than one scope to take action so we'd never check for multiple.

set_transient( 'auth0_api_token_scope', 'update:users' );

$this->http_request_type = 'success_empty_body';
$api = new WP_Auth0_Api_Change_Email( self::$opts, self::$api_client_creds );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Test that the bearer setting succeeds". Where is this setting being called here? Maybe you are not missing the call but the name of the test method should be different and not disclose "black box" internals.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically a generic test against set_bearer instead of reflecting/exposing. This class requires the bearer token to be set so I'm making sure that it is and checking that it was stored.

Where is this setting being called here?

I'm not clear on your question.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a question but rather an obversation. That the name of the test suggest you're going to call set_bearer but in the test you don't. It's true that you might be calling it internally when a new instance of WP_Auth0_Api_Change_Email is created, but the test should not know what methods are called internally. The test should only know that a new instance of WP_Auth0_Api_Change_Email is being created. That's why I mentioned to only test the "black box" of the method and not its internals.

@@ -20,7 +20,7 @@ class TestProfileChangePassword extends WP_Auth0_Test_Case {

use UsersHelper;

use httpHelpers;
use HttpHelpers;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're changing the case of the class name but the file name is still the same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File name is fine, will get picked up by the autoloader. Testing individual files failed when the case of the trait didn't match the case of the use statement.

set_transient( 'auth0_api_token_scope', 'update:users' );

$this->http_request_type = 'success_empty_body';
$api = new WP_Auth0_Api_Change_Email( self::$opts, self::$api_client_creds );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a question but rather an obversation. That the name of the test suggest you're going to call set_bearer but in the test you don't. It's true that you might be calling it internally when a new instance of WP_Auth0_Api_Change_Email is created, but the test should not know what methods are called internally. The test should only know that a new instance of WP_Auth0_Api_Change_Email is being created. That's why I mentioned to only test the "black box" of the method and not its internals.

$this->api_token_decoded = $this->api_client_creds->get_token_decoded();
// No stored API token so need to get a new one.
if ( ! $api_token && $this->api_client_creds instanceof WP_Auth0_Api_Client_Credentials ) {
$api_token = $this->api_client_creds->call();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this call aware of the required $scope?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it doesn't need to be. You get the scopes back that the Application is authorized for.

wp_cache_set( self::CACHE_KEY, $this->api_token, WPA0_CACHE_GROUP );
return true;
// Delete the stored token so we can try again.
WP_Auth0_Api_Client_Credentials::delete_store();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would you need to delete the token? What if the user wants to use the stored token for a different API endpoint call?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it tries again. We don't want the token stored without required scopes or else we can't try again.

/**
* Check the stored API token scope for a specific scope.
*
* @param string $scope - Scope to check for.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe clarify here that the scope param is for a single scope vs a space separated string of scopes. This was confusing to me on the initial review because when we build /authorize URLs we have a "scope" parameter that accepts as many scopes as wanted, separated by a space.

Copy link
Contributor Author

@joshcanhelp joshcanhelp Mar 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only for the client credentials grant (hence the class name) but I will make that more explicit.

@joshcanhelp joshcanhelp merged commit a78b427 into master Mar 15, 2019
@joshcanhelp joshcanhelp deleted the fix-m-api-token-handling branch March 15, 2019 19:55
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants