Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions src/class-convertkit-api-v4.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class ConvertKit_API_V4 {
*/
protected $api_endpoints_oauth = array(
'token',
'revoke',
);

/**
Expand Down Expand Up @@ -464,6 +465,89 @@ public function refresh_token() {

}

/**
* Revokes the current access and refresh tokens.
*
* @since 2.1.4
*/
public function revoke_tokens() {

// Revoke the access token.
$result = $this->post(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@mercedesb this will POST to https://api.kit.com/v4/oauth/revoke, sending the client_id and access_token to be revoked. Wanted to check this is the correct call, as couldn't spot any docs on the API site.

'revoke',
array(
'client_id' => $this->client_id,
'token' => $this->access_token,
)
);

// If an error occured, log and return it now.
if ( is_wp_error( $result ) ) {
$this->log( 'API: Error: ' . $result->get_error_message() );

/**
* Perform any actions when revoking an access token fails.
*
* @since 2.1.4
*
* @param WP_Error $result Error from API.
* @param string $client_id OAuth Client ID.
*/
do_action( 'convertkit_api_revoke_tokens_access_token_error', $result, $this->client_id );

return $result;
}

// Revoke the refresh token.
$result = $this->post(
'revoke',
array(
'client_id' => $this->client_id,
'token' => $this->refresh_token,
)
);

// If an error occured, log and return it now.
if ( is_wp_error( $result ) ) {
$this->log( 'API: Error: ' . $result->get_error_message() );

/**
* Perform any actions when revoking a refresh token fails.
*
* @since 2.1.4
*
* @param WP_Error $result Error from API.
* @param string $client_id OAuth Client ID.
*/
do_action( 'convertkit_api_revoke_tokens_refresh_token_error', $result, $this->client_id );

return $result;
}

// Store existing access and refresh tokens.
$previous_access_token = $this->access_token;
$previous_refresh_token = $this->refresh_token;

// Remove access and refresh tokens from this class.
$this->access_token = '';
$this->refresh_token = '';

/**
* Perform any actions when the tokens are revoked, such as deleting them from the database.
*
* @since 2.1.4
*
* @param string $client_id OAuth Client ID.
* @param string $previous_access_token Existing Access Token.
* @param string $previous_refresh_token Existing Refresh Token.
*/
do_action( 'convertkit_api_revoke_tokens', $this->client_id, $previous_access_token, $previous_refresh_token );

// Return.
return $result;

}

/**
* Exchanges the given API Key for an Access Token.
*
Expand Down
51 changes: 51 additions & 0 deletions tests/Integration/APITest.php
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,57 @@ public function testRefreshTokenWithInvalidToken()
$this->assertEquals($result->get_error_code(), 'convertkit_api_error');
}

/**
* Test that the access token and refresh token are revoked when revoke_tokens() is called.
*
* @since 2.1.4
*/
public function testRevokeTokens()
{
// Initialize the API without an access token or refresh token.
$api = new \ConvertKit_API_V4(
$_ENV['CONVERTKIT_OAUTH_CLIENT_ID'],
$_ENV['CONVERTKIT_OAUTH_REDIRECT_URI']
);

// Generate an access token by API key and secret.
$result = $api->get_access_token_by_api_key_and_secret(
$_ENV['CONVERTKIT_API_KEY'],
$_ENV['CONVERTKIT_API_SECRET'],
wp_generate_password( 10, false ) // Random tenant name to produce a token for this request only.
);

// Initialize the API with the access token and refresh token.
$api = new \ConvertKit_API_V4(
$_ENV['CONVERTKIT_OAUTH_CLIENT_ID'],
$_ENV['CONVERTKIT_OAUTH_REDIRECT_URI'],
$result['oauth']['access_token'],
$result['oauth']['refresh_token']
);

// Confirm the token works when making an authenticated request.
$this->assertNotInstanceOf( 'WP_Error', $api->get_account() );

// Revoke the access and refresh tokens.
$api->revoke_tokens();

// Initialize the API with the (now revoked) access token and refresh token.
// revoke_tokens() will have removed the access token and refresh token from the API class, so we need to provide them again
// to test they're revoked.
$api = new \ConvertKit_API_V4(
$_ENV['CONVERTKIT_OAUTH_CLIENT_ID'],
$_ENV['CONVERTKIT_OAUTH_REDIRECT_URI'],
$result['oauth']['access_token'],
$result['oauth']['refresh_token']
);

// Confirm attempting to use the revoked access token no longer works.
$this->assertInstanceOf( 'WP_Error', $api->get_account() );

// Confirm attempting to use the revoked refresh token no longer works.
$this->assertInstanceOf( 'WP_Error', $api->refresh_token() );
}

/**
* Test that supplying no API credentials to the API class returns a WP_Error.
*
Expand Down
Loading