From cfdf3aae9e98eed20ee92ee2ba37be9ab630f3ff Mon Sep 17 00:00:00 2001 From: Justin Foell Date: Mon, 3 Jun 2019 14:27:14 -0500 Subject: [PATCH] Added refresh cron and refresh method --- includes/WPStrava.php | 5 +- includes/WPStrava/Auth.php | 14 +++-- includes/WPStrava/AuthForever.php | 9 ++++ includes/WPStrava/AuthRefresh.php | 90 ++++++++++++++++++++++++++++--- includes/WPStrava/Settings.php | 25 +++++++-- 5 files changed, 128 insertions(+), 15 deletions(-) diff --git a/includes/WPStrava.php b/includes/WPStrava.php index 1ee5400..e905e0c 100644 --- a/includes/WPStrava.php +++ b/includes/WPStrava.php @@ -46,11 +46,12 @@ class WPStrava { */ private function __construct() { $this->settings = new WPStrava_Settings(); - $this->auth = WPStrava_Auth::get_auth( 'forever' ); + $this->auth = WPStrava_Auth::get_auth( 'refresh' ); + + $this->auth->hook(); if ( is_admin() ) { $this->settings->hook(); - $this->auth->hook(); } else { add_action( 'init', array( $this, 'register_shortcodes' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) ); diff --git a/includes/WPStrava/Auth.php b/includes/WPStrava/Auth.php index 0cd3e49..88719e7 100644 --- a/includes/WPStrava/Auth.php +++ b/includes/WPStrava/Auth.php @@ -24,8 +24,10 @@ abstract class WPStrava_Auth { abstract protected function get_authorize_url( $client_id ); public function hook() { - add_filter( 'pre_set_transient_settings_errors', array( $this, 'maybe_oauth' ) ); - add_action( 'admin_init', array( $this, 'init' ) ); + if ( is_admin() ) { + add_filter( 'pre_set_transient_settings_errors', array( $this, 'maybe_oauth' ) ); + add_action( 'admin_init', array( $this, 'init' ) ); + } } /** @@ -92,11 +94,13 @@ abstract class WPStrava_Auth { 'code' => $code, ); + $data = $this->add_initial_params( $data ); + $strava_info = $this->token_request( $data ); if ( isset( $strava_info->access_token ) ) { $settings->add_id( $client_id ); - $settings->save_info( $client_id, $strava_info ); + $settings->save_info( $client_id, $client_secret, $strava_info ); $this->feedback .= __( 'Successfully authenticated.', 'wp-strava' ); return $strava_info; @@ -117,4 +121,8 @@ abstract class WPStrava_Auth { return $api->post( 'oauth/token', $data ); } + protected function add_initial_params( $data ) { + return $data; + } + } diff --git a/includes/WPStrava/AuthForever.php b/includes/WPStrava/AuthForever.php index f0a2cad..bb11813 100644 --- a/includes/WPStrava/AuthForever.php +++ b/includes/WPStrava/AuthForever.php @@ -9,9 +9,18 @@ * AuthForever Class * * @since 2.0.0 + * @see http://developers.strava.com/docs/authentication/ */ class WPStrava_AuthForever extends WPStrava_Auth { + /** + * Authorize URL for old style forever tokens. + * + * @param int $client_id Strava API Client ID. + * @return string URL to authorize against. + * @author Justin Foell + * @since 2.0.0 + */ protected function get_authorize_url( $client_id ) { return add_query_arg( array( diff --git a/includes/WPStrava/AuthRefresh.php b/includes/WPStrava/AuthRefresh.php index a2397d8..998879c 100644 --- a/includes/WPStrava/AuthRefresh.php +++ b/includes/WPStrava/AuthRefresh.php @@ -4,14 +4,61 @@ * AuthRefresh class * * @since 2.0.0 + * @see http://developers.strava.com/docs/authentication/ */ class WPStrava_AuthRefresh extends WPStrava_Auth { + /** + * Hooks. + * + * @author Justin Foell + * @since 2.0.0 + */ public function hook() { parent::hook(); - // @TODO Need cronjob. + + // Refresh tokens via cronjob. + add_action( 'init', array( $this, 'setup_auth_refresh_cron' ) ); + add_action( 'wp_strava_auth_refresh_cron', array( $this, 'auth_refresh' ) ); } + /** + * Set up cron to refresh the auth token hourly (expires after 6-hours). + * + * @author Justin Foell + * @since 2.0.0 + */ + public function setup_auth_refresh_cron() { + + // Schedule the cron job to purge all expired transients. + if ( ! wp_next_scheduled( 'wp_strava_auth_refresh_cron' ) ) { + wp_schedule_event( time(), 'hourly', 'wp_strava_auth_refresh_cron' ); + } + } + + /** + * Cron method to refresh auth tokens from Strava. + * + * @author Justin Foell + * @since 2.0.0 + */ + public function auth_refresh() { + $settings = WPStrava::get_instance()->settings; + foreach ( $settings->info as $client_id => $info ) { + if ( ! empty( $info->refresh_token ) ) { + $this->token_exchange_refresh( $client_id, $info ); + } + } + } + + /** + * Authorize URL for new style refresh token auth. + * + * @param int $client_id Strava API Client ID. + * @return string URL to authorize against. + * @author Justin Foell + * @since 2.0.0 + */ protected function get_authorize_url( $client_id ) { return add_query_arg( array( @@ -24,21 +71,52 @@ class WPStrava_AuthRefresh extends WPStrava_Auth { ); } - protected function token_exchange_refresh() { + /** + * Add 'authorization_code' grand type to first API request (when authenticating a new user). + * + * @param array $data Request array for the Strava API. + * @return array Data array with 'grant_type' => 'authorization_code' added. + * @author Justin Foell + * @since 2.0.0 + */ + protected function add_initial_params( $data ) { + $data['grant_type'] = 'authorization_code'; + return $data; + } + + /** + * Extend access by contacting strava with a refresh token. + * + * @param int $client_id + * @param stdClass $info + * @return boolean True if refreshed successfully, false otherwise. + * @author Justin Foell + * @since 2.0.0 + */ + protected function token_exchange_refresh( $client_id, $info ) { $data = array( 'client_id' => $client_id, - 'client_secret' => $client_secret, - 'refresh_token' => $refresh_token, + 'client_secret' => $info->client_secret, + 'refresh_token' => $info->refresh_token, 'grant_type' => 'refresh_token', ); $strava_info = $this->token_request( $data ); if ( isset( $strava_info->access_token ) ) { - $this->feedback .= __( 'Successfully re-authenticated.', 'wp-strava' ); - return $strava_info; + $this->feedback .= __( 'ID %s successfully re-authenticated.', 'wp-strava' ); + + if ( $strava_info->access_token != $info->access_token ) { + $this->feedback .= __( 'ID %s access extended.', 'wp-strava' ); + + $settings = WPStrava::get_instance()->settings; + $settings->save_info( $client_id, $info->client_secret, $strava_info ); + } + + return true; } + // @TODO how to determine if refresh wasn't successful? $this->feedback .= sprintf( __( 'There was an error receiving data from Strava:
%s
', 'wp-strava' ), print_r( $strava_info, true ) ); // phpcs:ignore -- Debug output. return false; } diff --git a/includes/WPStrava/Settings.php b/includes/WPStrava/Settings.php index 56a46fa..6638284 100644 --- a/includes/WPStrava/Settings.php +++ b/includes/WPStrava/Settings.php @@ -398,18 +398,35 @@ class WPStrava_Settings { /** * Undocumented function * - * @param [type] $id - * @param [type] $info - * @return void + * @param int $id Strava API Client ID + * @param string $secret Strava API Client Secret + * @param stdClass $info * @author Justin Foell * @since 2.0.0 */ - public function save_info( $id, $info ) { + public function save_info( $id, $secret, $info ) { $infos = get_option( 'strava_info', array() ); + $infos = array_filter( $infos, array( $this, 'filter_by_id' ), ARRAY_FILTER_USE_KEY ); // Remove old IDs. + $info->client_secret = $secret; $infos[ $id ] = $info; update_option( 'strava_info', $infos ); } + /** + * array_filter() callback to remove info for IDs we no longer have. + * + * @param int $key Strava Client ID + * @return boolean True if Client ID is in $this->ids, false otherwise. + * @author Justin Foell + * @since 2.0.0 + */ + public function filter_by_id( $key ) { + if ( in_array( $key, $this->ids ) ) { + return true; + } + return false; + } + /** * Undocumented function *