Closed ToddEvansHome closed 3 years ago
The service account flow will also work just fine, if you were to use the GoogleAdsConfig approach. For instance,
GoogleAdsConfig config = new GoogleAdsConfig()
{
OAuth2ClientId = xxx,
OAuth2SecretsJsonPath = xxx,
OAuth2Scope = xxx,
OAuth2Mode = OAuth2Flow.SERVICE_ACCOUNT,
OAuth2PrnEmail = xxx
};
GoogleAdsClient_client = new GoogleAdsClient(config);
googleAdsService = _client.GetService(Services.V6.GoogleAdsService);
The minor caveat is that OAuth2Scope can only take a single string, not an array of strings. I can push a fix for this next week.
The service builder approach doesn't work because Google Ads services require additional wiring which is not supported by the default builder stubs. I'll mark them as internal to avoid confusion.
I have tried the following and receive the below exception
GoogleAdsConfig config = new GoogleAdsConfig() { OAuth2ClientId = "######", OAuth2SecretsJsonPath = "Keys/adbdff8f747f.json", OAuth2Scope = "https://www.googleapis.com/auth/adwords", OAuth2Mode = OAuth2Flow.SERVICE_ACCOUNT, OAuth2PrnEmail = "xxxxxxxxx.iam.gserviceaccount.com", DeveloperToken = "#######" };
Exception: Message: Status(StatusCode="Unauthenticated", Detail="Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1613243724.561000000","description": "Error received from peer ipv6:[2607:f8b0:4009:80f::200a]:443","file":"......\src\core\lib\surface\call.cc","file_line":1063, "grpc_message":"Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.","grpc_status":16}")
Failure: { "errors": [ { "errorCode": { "authenticationError": "NOT_ADS_USER" }, "message": "User in the cookie is not a valid Ads user." } ] } Request ID: aXZK5HWECFCmv6Qsi4s-Yw
The *.json file is the file we received from our Service Account
Hi,
The OAuth2PrnEmail
field should point to the email account in your GSuite domain you are impersonating. This user should also be a valid user in your Google Ads account.
The way you make the call seems fine to me.
Temporarily closing this issue, feel free to reopen if the issue persists.
We do not have a GSuite domain. The user we are using for OAuth2PrnEmail is the owner of the Google Ads account. We are currently getting the below error. How may we use Service Account without a GSuite domain.
An error occurred while authorizing the user.: System.AggregateException: One or more errors occurred. (Status(StatusCode="Unavailable", Detail="Getting metadata from plugin failed with error: Exception occurred in metadata credentials plugin. Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"unauthorized_client", Description:"Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.", Uri:""
at Google.Apis.Auth.OAuth2.Responses.TokenResponse.FromHttpResponseAsync(HttpResponseMessage response, IClock clock, ILogger logger)
at Google.Apis.Auth.OAuth2.Requests.TokenRequestExtenstions.ExecuteAsync(TokenRequest request, HttpClient httpClient, String tokenServerUrl, CancellationToken taskCancellationToken, IClock clock, ILogger logger)
at Google.Apis.Auth.OAuth2.ServiceAccountCredential.RequestAccessTokenAsync(CancellationToken taskCancellationToken)
at Google.Apis.Auth.OAuth2.TokenRefreshManager.RefreshTokenAsync()
at Google.Apis.Auth.OAuth2.TokenRefreshManager.GetAccessTokenForRequestAsync(CancellationToken cancellationToken)
at Google.Apis.Auth.OAuth2.ServiceAccountCredential.GetAccessTokenForRequestAsync(String authUri, CancellationToken cancellationToken)
at Google.Apis.Auth.OAuth2.ServiceCredential.GetAccessTokenWithHeadersForRequestAsync(String authUri, CancellationToken cancellationToken)
at Grpc.Auth.GoogleAuthInterceptors.<>c__DisplayClass3_0.<
@ToddEvansHome you cannot use service account setup with Google Ads without GSuite domain. That's a limitation of how Google Ads (the product) works, and not the .NET library per-se.
You need to do the installed application flow with offline access instead (the flow involving refresh tokens).
Hi Anash, Thank you for your quick response,
Clarification: We are using Google Workspace(formerly known as G Suite) and we do have both Google Ads & Google Ads Manager services enabled within the Google Admin.. The email I am adding to the OAuth2PrnEmail property is within Google Workspace and that email is "Service Account Token Creator Owner" role for our service account in Google Ads.
I must be missing something. Any help would be greatly appreciated.
On Thu, Mar 11, 2021 at 10:54 AM Anash P. Oommen @.***> wrote:
@ToddEvansHome https://github.com/ToddEvansHome you cannot use service account setup with Google Ads without GSuite domain. That's a limitation of how Google Ads (the product) works, and not the .NET library per-se.
You need to do the installed application flow with offline access instead (the flow involving refresh tokens).
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/googleads/google-ads-dotnet/issues/261#issuecomment-796883930, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKNJOY3FANJKPDPGOZHL6ULTDDRS7ANCNFSM4WXMIJHQ .
-- Thank you, Todd Evans Senior Programmer Media Management, Inc. 314-296-0007
-- https://www.linkedin.com/company/64239 https://twitter.com/MMi_mediaaudit https://www.facebook.com/MMiMediaAudit https://plus.google.com/u/0/107322038390188996620/posts http://www.mediaaudit.com/contact/watchdog-eblast/This e-mail and any files transmitted with it may contain confidential information and is intended solely for use by the individual to whom it is addressed. If you received this e-mail in error, please notify the sender, do not disclose the contents to others and delete it from your system.
Could anyone please explain me what's difference between Google Ads Api & Google Adwords Api ?
I think both are same.
I am receiving the following error message during a SearchStream requests _Status(StatusCode="InvalidArgument", Detail="Request contains an invalid argument.", DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1611847453.657000000","description":"Error received from peer ipv6:[2607:f8b0:4009:802::200a]:443","file":"......\src\core\lib\surface\call.cc","file_line":1063,"grpc_message":"Request contains an invalid argument.","grpcstatus":3}")
Which version of the client library are you using? Google.Ads.GoogleAds v6.1.0 Which version of .NET are you using? .NET 5 Which operating system (Linux, Windows, ...) and version? Windows
Actions taken `GoogleAdsServiceClient _googleAdsService;
public static ICredential GetGoogleServiceCredential() { var googleCredential = GetGoogleCredentialsFromJSONKey( "Keys/xxxxxxx.json",
new string[] { "https://www.googleapis.com/auth/sqlservice.admin", "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/adwords"} );
return googleCredential;
}`
`///Google Credential
/// Authenticate using a Service Account
///
/// Path to your JSON Key file
/// Scopes required in access token
///
public static ICredential GetGoogleCredentialsFromJSONKey(string jsonKeyFilePath, params string[] scopes) { using (var stream = new FileStream(jsonKeyFilePath, FileMode.Open, FileAccess.Read)) { return GoogleCredential .FromStream(stream) // Loads key file
.CreateScoped(scopes) // Gathers scopes requested
.UnderlyingCredential; // Gets the credentials
}`
` //This is a windows service starting point protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); await Task.Delay(1000, stoppingToken);
}`
// Make a simple query call private void Campaings_Get() { string query = "SELECT campaign.id, campaign.name FROM campaign"; GoogleAdsService_SearchStream(customerID, query, Campaings_Show); }
// Write results to console private void Campaings_Show(GoogleAdsRow googleAdsRow) { Console.WriteLine("Campaign with ID {0} and name '{1}' was found.", googleAdsRow.Campaign.Id, googleAdsRow.Campaign.Name); }
` // Query Google Ads protected void GoogleAdsService_SearchStream(long customerId, string query, Action}` Expected result "SearchGoogleAdsStreamResponse resp": is populated with records returned
Actual result One or more errors occurred. (Status(StatusCode="InvalidArgument", Detail="Request contains an invalid argument.", DebugException="Grpc.Core.Internal.CoreErrorDetailException: {"created":"@1611847453.657000000","description":"Error received from peer ipv6:[2607:f8b0:4009:802::200a]:443","file":"......\src\core\lib\surface\call.cc","file_line":1063,"grpc_message":"Request contains an invalid argument.","grpc_status":3}"))
Stack trace at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at System.Threading.Tasks.Task.Wait() at Google.Ads.GoogleAds.V6.Services.GoogleAdsServiceClient.SearchStream(String customerId, String query, Action
1 responseCallback, SummaryRowSetting summaryRowSetting, CallSettings callSettings) at PaidSearchWindowsService.Worker.GoogleAdsService_SearchStream(Int64 customerId, String query, Action
1 writeLine) in C:\MMiProjects\PaidSearchWindowsService\PaidSearchWindowsService\Worker.cs:line 277Anything else we should know about your project / environment If we use Google Desktop Client ID for authentication instead of Service Account calling the same query works.
We did this by first populating GoogleAdsConfig config, create GoogleAdsClient, then call GetService to acquire GoogleAdsServiceClient GoogleAdsClient_client = new GoogleAdsClient(config); // Get the GoogleAdsService. _googleAdsService = _client.GetService(Services.V6.GoogleAdsService);