-
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
Better Management API token handling #632
Conversation
23975e1
to
c1b56f6
Compare
Codecov Report
@@ 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
Continue to review full report at Codecov.
|
if ( ! $this->api_token ) { | ||
$this->api_token = $this->options->get( 'auth0_app_token' ); // REMOVE | ||
} | ||
$api_token = WP_Auth0_Api_Client_Credentials::get_stored_token(); |
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.
What's the reason to have this method static and the call()
one part of the instance instead?
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.
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 ) { |
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.
shouldn't this case be covered by a exception thrown in call()
if the request fails somehow?
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.
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 ) ) { |
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.
What is this line doing?
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.
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 ); |
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.
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
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.
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 ); |
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.
"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.
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.
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.
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.
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; |
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.
You're changing the case of the class name but the file name is still the same
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.
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 ); |
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.
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(); |
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.
is this call aware of the required $scope
?
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.
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(); |
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.
why would you need to delete the token? What if the user wants to use the stored token for a different API endpoint call?
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.
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. |
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.
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.
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.
This is only for the client credentials grant (hence the class name) but I will make that more explicit.
Changes
References
Closes #631
Testing
Checklist