Hi I'm trying to replicate the GetAccountHieararchy.php example on my Laravel application and I keep getting this aparently very common permissions error but I can't see whats the problem:
{ "message": "The caller does not have permission", "code": 7, "status": "PERMISSION_DENIED", "details": [ { "@type": "type.googleapis.com\/google.ads.googleads.v13.errors.GoogleAdsFailure", "errors": [ { "errorCode": { "authorizationError": "USER_PERMISSION_DENIED" }, "message": "User doesn't have permission to access customer. Note: If you're accessing a client customer, the manager's customer id must be set in the 'login-customer-id' header. See https:\/\/developers.google.com\/google-ads\/api\/docs\/concepts\/call-structure#cid" } ], "requestId": "HvUJs9KXJuoUXsX1rySSZg" } ] } Using a refresh token generated with the playground app and then placing it in th google_ads_php.ini works. But it doesn't with my implementation of the oauth2 login Is there something wrong or missing here? I see in the playground some parameters in the first step that I don't see here. This is not my implementation I'm just looking to understand and fix the permissions issue here. class MCCHierarchy { public function all() { $efGoogleAds = new EfGoogleAds(); return $this->createCustomerClientHierarchy($efGoogleAds); } private function createCustomerClientHierarchy(EfGoogleAds $efGoogleAds) { // First, fetch the list of accessible customers $outputArray = $this->getAccessibleCustomers($efGoogleAds-> getGoogleAdsClient()); $selects = ['customer_client.client_customer', 'customer_client.level', 'customer_client.manager', 'customer_client.descriptive_name', 'customer_client.currency_code', 'customer_client.time_zone', 'customer_client.id', 'customer_client.status']; $wheres = [ ['customer_client.level', '= 1'], ['customer_client.status', '= "ENABLED"'], ['customer_client.manager', '= true'] ]; // Now, we fetch subClients againsts each customer foreach ($outputArray as $key => $mccClient) { try{ $subAccountsStreamReport = new StreamReportGoogleAds('customer_client', $efGoogleAds->serviceClient, intval($mccClient['clientId']), $selects, $wheres, ''); }catch(\Google\ApiCore\ApiException $e){ Log::error('Client id failing: '.$mccClient['clientId']); if (isset($e->getMetadata()[0]["errors"][0]["errorCode"][ "authorizationError"]) && $e->getMetadata()[0]["errors"][0]["errorCode"][ "authorizationError"] === 'CUSTOMER_NOT_ENABLED') { // The customer account can't be accessed because it is not yet enabled or has been deactivated. // You may want to log this or handle differently in your application. continue; } else { throw $e; } } $subClientArray = []; $subClientIdsArray = []; try{ foreach ($subAccountsStreamReport->stream->iterateAllElements() as $subAccount) { $customerClient = $subAccount->getCustomerClient(); $subClientArray[] = [ 'clientName' => $customerClient->getDescriptiveName(), 'clientId' => $customerClient->getId(), 'manager' => $customerClient->getManager(), 'clientStatus' => CustomerStatus::name($customerClient->getStatus()) ]; $subClientIdsArray[] = [ "subClientName" => $customerClient->getDescriptiveName(), "subClientId" => $customerClient->getId() ]; } }catch(\Google\Ads\GoogleAds\Lib\V13\GoogleAdsException $e){ Log::error('Client id failing in second loop: '.$mccClient['clientId']); throw $e; } $outputArray[$key]['subClients'] = $subClientArray; $outputArray[$key]['subClientsIds'] = json_encode($subClientIdsArray); } //dd($outputArray); return $outputArray; } /** * Retrieves a list of accessible customers with the provided set up credentials. * * @param GoogleAdsClient $googleAdsClient the Google Ads API client * @return int[] the list of customer IDs */ private function getAccessibleCustomers(GoogleAdsClient $googleAdsClient): array { $outputArray = []; // Issues a request for listing all customers accessible by this authenticated Google // account. $customerServiceClient = $googleAdsClient->getCustomerServiceClient(); $accessibleCustomers = $customerServiceClient->listAccessibleCustomers([ 'customer.status' => 'ENABLED']); foreach ($accessibleCustomers->getResourceNames() as $customerResourceName) { $customer = CustomerServiceClient::parseName($customerResourceName)[ 'customer_id']; $outputArray[] = [ 'clientName' => $customerResourceName, 'clientId' => intval($customer), ]; } return $outputArray; } class GoogleAuthController extends Controller { private $client; public function __construct() { $this->client = new Google_Client(); $this->client->setClientId(env('GOOGLE_ADS_CLIENT_ID')); $this->client->setClientSecret(env('GOOGLE_ADS_CLIENT_SECRET')); $this->client->setRedirectUri(env('GOOGLE_ADS_REDIRECT_URI')); $this->client->addScope('https://www.googleapis.com/auth/adwords'); } public function login() { $authUrl = $this->client->createAuthUrl(); return redirect($authUrl); } public function callback(Request $request) { if (!$request->has('code')) { return redirect()->route('login')->withErrors('Authorization failed.'); } $accessToken = $this->client->fetchAccessTokenWithAuthCode($request->get( 'code')); session([ 'google_ads_access_token' => $accessToken ]); return redirect()->route('keywordurls'); } public function logout() { session()->forget('google_ads_access_token'); return redirect()->route('login'); } } class EfGoogleAds { public $serviceClient = null; public $fieldServiceClient = null; private GoogleAdsClient $googleAdsClient; public function __construct() { $this->setGoogleAdsClient(); $this->serviceClient = $this->googleAdsClient->getGoogleAdsServiceClient(); $this->fieldServiceClient = $this->googleAdsClient-> getGoogleAdsFieldServiceClient(); } private function setGoogleAdsClient() { $oAuth2Credential = (new OAuth2TokenBuilder()) ->withClientId(env('GOOGLE_ADS_CLIENT_ID')) ->withClientSecret(env('GOOGLE_ADS_CLIENT_SECRET')) ->withRefreshToken(session('google_ads_access_token')['access_token']) // Use the stored refresh token ->build(); $this->googleAdsClient = (new GoogleAdsClientBuilder()) ->withDeveloperToken(env('GOOGLE_ADS_DEVELOPER_TOKEN')) ->withOAuth2Credential($oAuth2Credential) ->build(); } public function getGoogleAdsClient(): GoogleAdsClient{ return $this->googleAdsClient; } } -- -- =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ Also find us on our blog: https://googleadsdeveloper.blogspot.com/ =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ You received this message because you are subscribed to the Google Groups "AdWords API and Google Ads API Forum" group. To post to this group, send email to adwords-api@googlegroups.com To unsubscribe from this group, send email to adwords-api+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/adwords-api?hl=en --- You received this message because you are subscribed to the Google Groups "Google Ads API and AdWords API Forum" group. To unsubscribe from this group and stop receiving emails from it, send an email to adwords-api+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/adwords-api/d1b9c90b-6766-4279-885d-4847e0cdc33dn%40googlegroups.com.