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

Prompt to reset the Meetup API authentication tokens, as we can't do it automatically. #317

Open
wants to merge 2 commits into
base: trunk
Choose a base branch
from
Open
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
18 changes: 15 additions & 3 deletions mu-plugins/utilities/class-meetup-client.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class Meetup_Client extends API_Client {
* }
*/
public function __construct( array $settings = array() ) {
// Define the OAuth client first, such that it can be used in the parent constructor callbacks.
$this->oauth_client = new Meetup_OAuth2_Client;

parent::__construct( array(
/*
* Response codes that should break the request loop.
Expand Down Expand Up @@ -86,13 +89,12 @@ public function __construct( array $settings = array() ) {
self::cli_message( 'Meetup Client debug is on. Results will be truncated.' );
}

$this->oauth_client = new Meetup_OAuth2_Client();
add_action( 'api_client_tenacious_remote_request_attempt', array( $this, 'maybe_reset_oauth_token' ) );
add_action( 'api_client_handle_error_response', array( $this, 'maybe_reset_oauth_token' ) );

if ( ! empty( $this->oauth_client->error->get_error_messages() ) ) {
$this->error = $this->merge_errors( $this->error, $this->oauth_client->error );
}

add_action( 'api_client_tenacious_remote_request_attempt', array( $this, 'maybe_reset_oauth_token' ) );
}

/**
Expand All @@ -106,6 +108,12 @@ public function __construct( array $settings = array() ) {
* @return void
*/
public function maybe_reset_oauth_token( $response ) {
static $resetting = false;
// Avoid recursive calls.
if ( $resetting ) {
return;
}

$code = wp_remote_retrieve_response_code( $response );
$body = json_decode( wp_remote_retrieve_body( $response ), true );

Expand All @@ -115,6 +123,8 @@ public function maybe_reset_oauth_token( $response ) {
( 400 === $code && $parsed_error->get_error_message( 'invalid_grant' ) )
|| ( 401 === $code && $parsed_error->get_error_message( 'auth_fail' ) )
) {
$resetting = true;

$this->oauth_client->reset_oauth_token();

if ( ! empty( $this->oauth_client->error->get_error_messages() ) ) {
Expand All @@ -123,6 +133,8 @@ public function maybe_reset_oauth_token( $response ) {

// Reset the request headers, so that they include the new oauth token.
$this->current_request_args = $this->get_request_args();

$resetting = false;
}
}

Expand Down
73 changes: 37 additions & 36 deletions mu-plugins/utilities/class-meetup-oauth2-client.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public function __construct() {
* See API_Client::tenacious_remote_request.
*/
'breaking_response_codes' => array(
400, // Bad request.
400, // Bad request. This happens for invalid_grant during refresh
401, // Unauthorized (invalid key).
429, // Too many requests (rate-limited).
404, // Unable to find group
Expand Down Expand Up @@ -219,48 +219,49 @@ public function get_oauth_token() {
return $this->oauth_token['access_token'];
}

// Get cached access token
$token = get_site_option( self::SITE_OPTION_KEY_OAUTH, array() );
$valid = $this->is_valid_token( $token, 'access_token' );

if ( ! $this->is_valid_token( $token, 'access_token' ) ) {

// At this point, we need to get a new oAuth done.
if ( empty( $_GET['code'] ) ) {
$_GET['code'] = get_site_option( self::SITE_OPTION_KEY_AUTHORIZATION, false );

if ( ! $_GET['code'] ) {
$message = sprintf(
"Meetup.com oAuth expired. Please access the following url while logged into the %s meetup.com account: \n\n%s\n\n" .
"For sites other than WordCamp Central, the ?code=... parameter will need to be stored on this site via wp-cli and this task run again: `wp --url=%s site option update '%s' '...'`",
self::EMAIL,
sprintf(
'https://secure.meetup.com/oauth2/authorize?client_id=%s&response_type=code&redirect_uri=%s&state=meetup-oauth',
self::CONSUMER_KEY,
self::REDIRECT_URI
),
network_site_url('/'),
self::SITE_OPTION_KEY_AUTHORIZATION
);

if ( admin_url( '/' ) === self::REDIRECT_URI ) {
printf( '<div class="notice notice-error"><p>%s</p></div>', nl2br( make_clickable( $message ) ) );
}

trigger_error( $message, E_USER_WARNING );

return false;
// If it's a valid token, but expired, refresh it.
if ( $valid && $this->is_expired_token( $token ) ) {
$token = $this->request_token( 'refresh_token', $token );
$valid = $this->is_valid_token( $token, 'access_token' );
}

// If it's not a valid token, or the refresh token wasn't valid, check to see if we're able to fetch a new one.
if ( ! $valid ) {
$auth_code = $_GET['code'] ?? get_site_option( self::SITE_OPTION_KEY_AUTHORIZATION, false );

if ( $auth_code ) {
$token = $this->request_token( 'access_token', array( 'code' => $auth_code ) );
$valid = $this->is_valid_token( $token, 'access_token' );
if ( $valid ) {
delete_site_option( self::SITE_OPTION_KEY_AUTHORIZATION, false );
}
}
}

$token = $this->request_token( 'access_token', array( 'code' => $_GET['code'] ) );
// If we're unable to find a valid token, and we're not mid-refresh, throw a Warning & Notice.
if ( ! $valid ) {
$message = sprintf(
"Meetup.com oAuth expired. Please access the following url while logged into the %s meetup.com account: \n\n%s\n\n" .
"For sites other than WordCamp Central, the ?code=... parameter will need to be stored on this site via wp-cli and this task run again: `wp --url=%s site option update '%s' '...'`",
self::EMAIL,
sprintf(
'https://secure.meetup.com/oauth2/authorize?client_id=%s&response_type=code&redirect_uri=%s&state=meetup-oauth',
self::CONSUMER_KEY,
self::REDIRECT_URI
),
network_site_url('/'),
self::SITE_OPTION_KEY_AUTHORIZATION
);

if ( $this->is_valid_token( $token, 'access_token' ) ) {
delete_site_option( self::SITE_OPTION_KEY_AUTHORIZATION, false );
if ( admin_url( '/' ) === self::REDIRECT_URI ) {
printf( '<div class="notice notice-error"><p>%s</p></div>', nl2br( make_clickable( $message ) ) );
}
} elseif ( $this->is_expired_token( $token ) ) {
$token = $this->request_token( 'refresh_token', $token );
}
trigger_error( $message, E_USER_WARNING );

if ( ! $this->is_valid_token( $token, 'access_token' ) ) {
return false;
}

Expand All @@ -283,7 +284,7 @@ public function get_oauth_token() {
public function reset_oauth_token() {
// NO. JUST NO. Do not delete the oAuth token.
// This is temporarily disabled while Meetup.com server-to-server authentication is unavailable.
// delete_site_option( self::SITE_OPTION_KEY_OAUTH );
delete_site_option( self::SITE_OPTION_KEY_OAUTH );

$this->oauth_token = array();
$this->error = new WP_Error();
Expand Down
Loading