-
Notifications
You must be signed in to change notification settings - Fork 22
[API Pull] Auth Flow #2424
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
[API Pull] Auth Flow #2424
Changes from 22 commits
1b2ff1f
8a769ba
74fd4cb
3d8c043
0abe152
74300c5
aa33687
b4173b6
3d5aa55
5b9a462
436881c
ece73b1
ca4e95c
f70f89e
bba7b0c
6fee5bd
bfdca07
e6fd185
b9ce5da
d156117
08c9b61
ec1e862
e42f728
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,9 @@ | |
use Automattic\WooCommerce\GoogleListingsAndAds\Utility\DateTimeUtility; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Value\TosAccepted; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Vendor\GuzzleHttp\Client; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Vendor\Psr\Container\ContainerExceptionInterface; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Vendor\Psr\Container\ContainerInterface; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Vendor\Psr\Container\NotFoundExceptionInterface; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Vendor\Psr\Http\Client\ClientExceptionInterface; | ||
use DateTime; | ||
use Exception; | ||
|
@@ -482,6 +484,19 @@ protected function get_manager_url( string $name = '' ): string { | |
return $name ? trailingslashit( $url ) . $name : $url; | ||
} | ||
|
||
/** | ||
* Get the Google Shopping Data Integration auth endpoint URL | ||
* | ||
* @return string | ||
*/ | ||
public function get_sdi_auth_endpoint(): string { | ||
return $this->container->get( 'connect_server_root' ) | ||
. 'google/google-sdi/v1/credentials/partners/WOO_COMMERCE/merchants/' | ||
. $this->strip_url_protocol( $this->get_site_url() ) | ||
. '/oauth/redirect:generate' | ||
. '?merchant_id=' . $this->options->get_merchant_id(); | ||
} | ||
|
||
/** | ||
* Generate a descriptive name for a new account. | ||
* Use site name if available. | ||
|
@@ -552,4 +567,45 @@ public function is_subaccount(): bool { | |
// since transients don't support booleans, we save them as 0/1 and do the conversion here | ||
return boolval( $is_subaccount ); | ||
} | ||
|
||
/** | ||
* Performs a request to Google Shopping Data Integration (SDI) to get required information in order to form an auth URL. | ||
* | ||
* @return array An array with the JSON response from the WCS server. | ||
* @throws NotFoundExceptionInterface When the container was not found. | ||
* @throws ContainerExceptionInterface When an error happens while retrieving the container. | ||
* @throws Exception When the response status is not successful. | ||
* @see google-sdi in google/services inside WCS | ||
*/ | ||
public function get_sdi_auth_params() { | ||
try { | ||
/** @var Client $client */ | ||
$client = $this->container->get( Client::class ); | ||
$result = $client->get( $this->get_sdi_auth_endpoint() ); | ||
$response = json_decode( $result->getBody()->getContents(), true ); | ||
|
||
if ( 200 !== $result->getStatusCode() ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @jorgemd24 How did you simulate the bad response? When I do so I cannot reproduce the error you mentioned. Screen.Recording.2024-06-26.at.14.01.27.movI did the simulation doing: $result = new Response(400 );
$response = []; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah sorry! I realized that my simulation was not correct, because I changed this line from |
||
do_action( | ||
'woocommerce_gla_partner_app_auth_failure', | ||
[ | ||
'error' => 'response', | ||
'response' => $response, | ||
] | ||
); | ||
do_action( 'woocommerce_gla_guzzle_invalid_response', $response, __METHOD__ ); | ||
$error = $response['message'] ?? __( 'Invalid response authenticating partner app.', 'google-listings-and-ads' ); | ||
throw new Exception( $error, $result->getStatusCode() ); | ||
} | ||
|
||
return $response; | ||
|
||
} catch ( ClientExceptionInterface $e ) { | ||
do_action( 'woocommerce_gla_guzzle_client_exception', $e, __METHOD__ ); | ||
|
||
throw new Exception( | ||
$this->client_exception_message( $e, __( 'Error authenticating Google Partner APP.', 'google-listings-and-ads' ) ), | ||
$e->getCode() | ||
); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,11 +3,16 @@ | |
|
||
namespace Automattic\WooCommerce\GoogleListingsAndAds\API\WP; | ||
|
||
use Automattic\Jetpack\Connection\Client; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\API\Google\Middleware; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\HelperTraits\Utilities as UtilitiesTrait; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Internal\ContainerAwareTrait; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Internal\Interfaces\ContainerAwareInterface; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Options\OptionsAwareInterface; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Options\OptionsAwareTrait; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Options\OptionsInterface; | ||
use Automattic\WooCommerce\GoogleListingsAndAds\Vendor\Google\Exception; | ||
use Jetpack_Options; | ||
|
||
defined( 'ABSPATH' ) || exit; | ||
|
@@ -19,12 +24,14 @@ | |
* @since x.x.x | ||
* @package Automattic\WooCommerce\GoogleListingsAndAds\API\WP | ||
*/ | ||
class OAuthService implements Service, OptionsAwareInterface { | ||
class OAuthService implements Service, OptionsAwareInterface, ContainerAwareInterface { | ||
|
||
use OptionsAwareTrait; | ||
use UtilitiesTrait; | ||
use ContainerAwareTrait; | ||
|
||
public const AUTH_URL = 'https://public-api.wordpress.com/oauth2/authorize'; | ||
public const WPCOM_API_URL = 'https://public-api.wordpress.com'; | ||
public const AUTH_URL = '/oauth2/authorize'; | ||
public const RESPONSE_TYPE = 'code'; | ||
public const SCOPE = 'wc-partner-access'; | ||
|
||
|
@@ -91,31 +98,72 @@ | |
'scope' => self::SCOPE, | ||
'state' => $state, | ||
], | ||
self::AUTH_URL | ||
$this->get_wpcom_api_url( self::AUTH_URL ) | ||
) | ||
); | ||
|
||
return $auth_url; | ||
} | ||
|
||
/** | ||
* Calls an API by Google to get required information in order to form an auth URL. | ||
* Get a WPCOM REST API URl concatenating the endpoint with the API Domain | ||
* | ||
* TODO: Call an actual API by Google. | ||
* We'd probably need use WCS to communicate with the new API. | ||
* @param string $endpoint The endpoint to get the URL for | ||
* | ||
* @return string The WPCOM endpoint with the domain. | ||
*/ | ||
protected function get_wpcom_api_url( string $endpoint ): string { | ||
return self::WPCOM_API_URL . $endpoint; | ||
} | ||
|
||
/** | ||
* Calls an API by Google via WCS to get required information in order to form an auth URL. | ||
* | ||
* @return array{client_id: string, redirect_uri: string, nonce: string} An associative array contains required information that is retrived from Google. | ||
* client_id: Google's WPCOM app client ID, will be used to form the authorization URL. | ||
* redirect_uri: A Google's URL that will be redirected to when the merchant approve the app access. Note that it needs to be matched with the Google WPCOM app client settings. | ||
* nonce: A string returned by Google that we will put it in the auth URL and the redirect_uri. Google will use it to verify the call. | ||
*/ | ||
protected function get_data_from_google(): array { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tweaked here |
||
$nonce = 'nonce-123'; | ||
/** @var Middleware $middleware */ | ||
$middleware = $this->container->get( Middleware::class ); | ||
$response = $middleware->get_sdi_auth_params(); | ||
$nonce = $response['nonce']; | ||
$this->options->update( OptionsInterface::GOOGLE_WPCOM_AUTH_NONCE, $nonce ); | ||
return [ | ||
'client_id' => '91299', | ||
'redirect_uri' => 'https://woo.com', | ||
'client_id' => $response['clientId'], | ||
'redirect_uri' => $response['redirectUri'], | ||
'nonce' => $nonce, | ||
]; | ||
} | ||
|
||
/** | ||
* Perform a remote request for revoking OAuth access for the current user. | ||
* | ||
* @return string The body of the response | ||
* @throws Exception If the remote request fails. | ||
*/ | ||
public function revoke_wpcom_api_auth(): string { | ||
$args = [ | ||
'method' => 'DELETE', | ||
'timeout' => 30, | ||
'url' => $this->get_wpcom_api_url( '/wpcom/v2/sites/' . Jetpack_Options::get_option( 'id' ) . '/wc/partners/google/revoke-token' ), | ||
'user_id' => get_current_user_id(), | ||
]; | ||
|
||
$request = Client::remote_request( $args ); | ||
|
||
if ( is_wp_error( $request ) ) { | ||
throw new Exception( $request->get_error_message(), $request->get_error_code() ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Exception expects the second parameter to be an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tweaked here. I will return just 400 |
||
} else { | ||
$body = wp_remote_retrieve_body( $request ); | ||
$status = wp_remote_retrieve_response_code( $request ); | ||
if ( 200 !== wp_remote_retrieve_response_code( $request ) ) { | ||
$data = json_decode( $body, true ); | ||
throw new Exception( $data['message'] ?? 'Error revoking access to WPCOM.', $status ); | ||
} | ||
|
||
return $body; | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.