Making WordPress.org

Changeset 11498


Ignore:
Timestamp:
02/01/2022 05:14:25 AM (3 years ago)
Author:
dd32
Message:

Official WordPress Events: During the Meetup.com REST API > GraphQL migration, part of the authentication layer was deactivated, switch authentication methods.

This commit is very not-preferential-approach, but works, which is better than the code in production :)

A human is required to go through the oAuth flow, rather than letting the code perform the login, which is why this is somewhat ugly.

See https://github.com/WordPress/wordcamp.org/issues/697

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/official-wordpress-events/meetup/class-meetup-oauth2-client.php

    r9223 r11498  
    7272     * @var string
    7373     */
    74     const SITE_OPTION_KEY_OAUTH = 'meetup_oauth_token';
     74    const SITE_OPTION_KEY_OAUTH = 'meetup_access_token';
     75
     76    /**
     77     * @var string
     78     */
     79    const SITE_OPTION_KEY_AUTHORIZATION = 'meetup_oauth_authorization';
    7580
    7681    /**
     
    122127
    123128    /**
    124      * Step 1 in "Server Flow with User Credentials".
    125      *
    126      * @see https://www.meetup.com/meetup_api/auth/#oauth2servercredentials-auth
    127      *
    128      * @return array
    129      */
    130     protected function request_authorization_code() {
    131         $authorization_code = array();
    132 
    133         $request = array(
    134             'client_id'     => self::CONSUMER_KEY,
    135             'redirect_uri'  => self::REDIRECT_URI,
    136             'response_type' => 'anonymous_code',
    137         );
    138 
    139         $args = array(
    140             'headers' => $this->get_headers(),
    141             'body'    => $request,
    142         );
    143 
    144         $response = $this->tenacious_remote_post( self::URL_AUTHORIZE, $args );
    145 
    146         if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
    147             $body = json_decode( wp_remote_retrieve_body( $response ), true );
    148 
    149             if ( ! empty( $body['code'] ) ) {
    150                 $authorization_code = $body;
    151             } else {
    152                 $this->error->add(
    153                     'unexpected_oauth_authorization_code_response',
    154                     'The Meetup OAuth API response did not provide the expected data.'
    155                 );
    156             }
    157         } else {
    158             $this->handle_error_response( $response );
    159         }
    160 
    161         return $authorization_code;
    162     }
    163 
    164     /**
    165129     * Request one of various types of tokens from the Meetup OAuth API.
    166      *
    167      * Setting $type to 'server_token' is for Step 2 in "Server Flow with User Credentials". This gets the "server
    168      * access token" which is then used to request the "oauth access token".
    169      * @see https://www.meetup.com/meetup_api/auth/#oauth2servercredentials-access
    170      *
    171      * Setting $type to 'oauth_token' is for Step 3 in "Server Flow with User Credentials". Technically in the
    172      * documentation, this token is also called an "access token", but here we're calling it the "oauth access token" to
    173      * differentiate it from the "server access token". Also, why are two separate access tokens necessary??
    174      * @see https://www.meetup.com/meetup_api/auth/#oauth2servercredentials-accesspro
    175      *
    176      * Setting $type to 'refresh_token' will request a new server access token for Step 2. This is for when the oauth
    177      * token from Step 3 is expired. The refreshed server token can then be used to obtain a new Step 3
    178      * oauth token. This skips the authorization code request (Step 1), but seems largely superfluous since a second
    179      * oauth token request must still be made with the new server token. Also, the refresh_token string used to refresh
    180      * the server token needs to come from the oauth token array, **not the server token array**. This is not what the
    181      * documentation implies. Why is this so terrible??
    182      * @see https://www.meetup.com/meetup_api/auth/#oauth2server-refresh
     130     *
     131     * Setting $type to 'access_token' is for step 2 of the oAuth flow. This takes a code that has been previously set
     132     * through a user-initiated oAuth authentication.
     133     *
     134     * Setting $type to 'refresh_token' will request a new access_token generated through the above access_token method.
     135     *
     136     * @see https://www.meetup.com/api/authentication/#p02-server-flow-section
    183137     *
    184138     * Check the `get_oauth_token` method to see how these token request flows work.
     
    197151
    198152        switch( $type ) {
    199             case 'server_token': // Request a new server access token.
     153            case 'access_token': // Request a new access token.
    200154                $args = wp_parse_args( $args, array(
    201155                    'code' => '',
     
    206160                    'client_id'     => self::CONSUMER_KEY,
    207161                    'client_secret' => self::CONSUMER_SECRET,
     162                    'grant_type'    => 'authorization_code',
    208163                    'redirect_uri'  => self::REDIRECT_URI,
    209164                    'code'          => $args['code'],
    210                     'grant_type'    => 'anonymous_code',
    211                 );
     165                );
     166                $request_headers['Content-Type'] = 'application/x-www-form-urlencoded';
    212167                break;
    213             case 'refresh_token': // Refresh a server access token.
     168
     169            case 'refresh_token': // Refresh an access token.
    214170                $args = wp_parse_args( $args, array(
    215171                    'refresh_token' => '',
     
    222178                    'refresh_token' => $args['refresh_token'],
    223179                    'grant_type'    => 'refresh_token',
    224                 );
    225                 break;
    226             case 'oauth_token': // Request a new oauth token.
    227                 $args = wp_parse_args( $args, array(
    228                     'access_token' => '',
    229                 ) );
    230 
    231                 $request_url     = self::URL_OAUTH_TOKEN;
    232                 $request_headers = $this->get_headers( $args['access_token'] );
    233                 $request_body    = array(
    234                     'email'    => self::EMAIL,
    235                     'password' => self::PASSWORD,
    236180                );
    237181                break;
     
    281225    public function get_oauth_token() {
    282226        if ( $this->oauth_token && ! $this->is_expired_token( $this->oauth_token ) ) {
    283             return $this->oauth_token['oauth_token'];
    284         }
    285 
    286         $oauth_token   = '';
    287         $needs_caching = false;
     227            return $this->oauth_token['access_token'];
     228        }
    288229
    289230        $token = get_site_option( self::SITE_OPTION_KEY_OAUTH, array() );
    290231
    291         if ( ! $this->is_valid_token( $token, 'oauth_token' ) ) {
    292             $authorization = $this->request_authorization_code(); // Step 1.
    293             $server_token  = $this->request_token( 'server_token', $authorization ); // Step 2.
    294             $token         = $this->request_token( 'oauth_token', $server_token ); // Step 3.
    295             $needs_caching = true;
     232        if ( ! $this->is_valid_token( $token, 'access_token' ) ) {
     233
     234            // At this point, we need to get a new oAuth done.
     235            if ( empty( $_GET['code'] ) ) {
     236                $_GET['code'] = get_site_option( self::SITE_OPTION_KEY_AUTHORIZATION, false );
     237
     238                if ( ! $_GET['code'] ) {
     239                    $message = sprintf(
     240                        "Meetup.com oAuth expired. Please access the following url while logged into the %s meetup.com account: \n\n%s\n\n" .
     241                        "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' '...'`",
     242                        self::EMAIL,
     243                        sprintf(
     244                            'https://secure.meetup.com/oauth2/authorize?client_id=%s&response_type=code&redirect_uri=%s&state=meetup-oauth',
     245                            self::CONSUMER_KEY,
     246                            self::REDIRECT_URI
     247                        ),
     248                        network_site_url('/'),
     249                        self::SITE_OPTION_KEY_AUTHORIZATION
     250                    );
     251
     252                    if ( admin_url( '/' ) === self::REDIRECT_URI ) {
     253                        printf( '<div class="notice notice-error"><p>%s</p></div>', nl2br( make_clickable( $message ) ) );
     254                    }
     255
     256                    trigger_error( $message, E_USER_WARNING );
     257
     258                    return false;
     259                }
     260            }
     261
     262            $token = $this->request_token( 'access_token', array( 'code' => $_GET['code'] ) );
     263
     264            if ( $this->is_valid_token( $token, 'access_token' ) ) {
     265                delete_site_option( self::SITE_OPTION_KEY_AUTHORIZATION, false );
     266            }
     267
    296268        } elseif ( $this->is_expired_token( $token ) ) {
    297             $server_token = $this->request_token( 'refresh_token', $token ); // Alternate for Steps 1 & 2.
    298 
    299             // If the token is no longer valid but "looked valid" fetch a fresh one.
    300             if ( ! $server_token && $this->error->get_error_message( 'oauth_error' ) ) {
    301                 $this->error->remove( 'oauth_error' );
    302 
    303                 // The token isn't valid for refreshing, request a new one.
    304                 $authorization = $this->request_authorization_code(); // Step 1.
    305                 $server_token  = $this->request_token( 'server_token', $authorization ); // Step 2.
    306             }
    307 
    308             $token         = $this->request_token( 'oauth_token', $server_token ); // Step 3.
    309             $needs_caching = true;
    310         }
    311 
    312         if ( $this->is_valid_token( $token, 'oauth_token' ) ) {
    313             $this->oauth_token = $token;
    314 
    315             if ( $needs_caching ) {
    316                 update_site_option( self::SITE_OPTION_KEY_OAUTH, $token );
    317             }
    318 
    319             $oauth_token = $this->oauth_token['oauth_token'];
    320         }
    321 
    322         return $oauth_token;
     269            $token = $this->request_token( 'refresh_token', $token );
     270        }
     271
     272        if ( ! $this->is_valid_token( $token, 'access_token' ) ) {
     273            return false;
     274        }
     275
     276        $this->oauth_token = $token;
     277
     278        update_site_option( self::SITE_OPTION_KEY_OAUTH, $this->oauth_token );
     279
     280        return $this->oauth_token['access_token'];
    323281    }
    324282
     
    333291     */
    334292    public function reset_oauth_token() {
    335         delete_site_option( self::SITE_OPTION_KEY_OAUTH );
     293        // NO. JUST NO. Do not delete the oAuth token.
     294        // This is temporarily disabled while Meetup.com server-to-server authentication is unavailable.
     295        // delete_site_option( self::SITE_OPTION_KEY_OAUTH );
    336296
    337297        $this->oauth_token = array();
     
    350310     */
    351311    protected function is_valid_token( $token, $type ) {
    352         $valid_types = array( 'server_token', 'refresh_token', 'oauth_token' );
     312        $valid_types = array( 'refresh_token', 'access_token' );
    353313
    354314        if ( ! is_array( $token ) || ! in_array( $type, $valid_types, true ) ) {
     
    357317
    358318        switch ( $type ) {
    359             case 'server_token':
    360319            case 'refresh_token':
    361320                $required_properties = array(
     
    363322                );
    364323                break;
    365             case 'oauth_token':
     324            case 'access_token':
    366325            default:
    367326                $required_properties = array(
    368                     'oauth_token'   => '',
     327                    'access_token'   => '',
    369328                    'refresh_token' => '',
    370329                    'expires_in'    => '',
Note: See TracChangeset for help on using the changeset viewer.