googleads / google-ads-ruby

Google Ads API Ruby Client Library
https://developers.google.com/google-ads/api/
Apache License 2.0
70 stars 65 forks source link

Argument to CallCredentials#new must be a proc (TypeError) #303

Closed mattparlane closed 10 months ago

mattparlane commented 3 years ago

I have an existing adwords_api integration that I am migrating to google/ads/google_ads. I am running the following:

require 'google/ads/google_ads'
adwords = Google::Ads::GoogleAds::GoogleAdsClient.new("/root/wg/ruby/lib/google_ads_config.rb")
ga_service = adwords.service.google_ads

and I get this:

Traceback (most recent call last):
        4: from test.rb:3:in `<main>'
        3: from /usr/local/lib/ruby/gems/2.7.0/gems/google-ads-googleads-10.0.0/lib/google/ads/google_ads/google_ads_client.rb:126:in `service'
        2: from /usr/local/lib/ruby/gems/2.7.0/gems/google-ads-googleads-10.0.0/lib/google/ads/google_ads/google_ads_client.rb:148:in `make_channel'
        1: from /usr/local/lib/ruby/gems/2.7.0/gems/google-ads-googleads-10.0.0/lib/google/ads/google_ads/google_ads_client.rb:148:in `new'
/usr/local/lib/ruby/gems/2.7.0/gems/google-ads-googleads-10.0.0/lib/google/ads/google_ads/google_ads_client.rb:148:in `initialize': Argument to CallCredentials#new must be a proc (TypeError)

Happy to provide a redacted config file if necessary. I'm using a service account so I have keyfile and impersonate set. I have also edited GoogleAdsClient#make_channel to look at what get_credentials produces, and it's a Google::Auth::Credentials object that looks all correct to me, again happy to provide a redacted dump of that object.

I'm sure I'm doing something wrong, but I don't know what... help?!

Thanks!

mcloonan commented 3 years ago

Thanks for reporting. I think this may be an issue with the library itself. Since service accounts are pretty rarely used, I think we just didn't notice when this broke after a change was made in the code.

I'll look into this further. In the meanwhile, you could use the config.authentication field to manually set up a service account correctly, or use a non-service-account authentication method (which is generally the recommended approach for the Google Ads API).

noctivityinc commented 2 years ago

@mcloonan Im getting this same error with a service account json file and v.10.0.0. I dont understand why you are saying to not use a service account. The only use we have for the API is to pull our own daily spend data, so it seems that a service account would make the most sense. We also cannot get a developed API token from the Google Ads console either, so were using a service account.

Regardless, we have our keyfile in the config folder and then we are referencing everything as

  c.keyfile = File.join(Rails.root, 'config', 'google-ads.json')
  c.impersonate = 'dmvcs-service-account@XXXXX-ads-reporting.iam.gserviceaccount.com'

In terms of using c.authentication instead, there is no documentation on how we would use that instead with the key file, so Im unclear on how to proceed

noctivityinc commented 2 years ago

FYI, if we do use it like this:

  c.authentication = {
    "type": "service_account",
    ...

We get the same error

mcloonan commented 2 years ago

The fix I made was after the 10.0.0 version of the library, so you should update to a more recent version which incorporates that fix. In fact, I don't believe 10.0.0 supports any modern version of the API, so you wouldn't be able to use it anyway.

Service accounts are not the preferred way to authenticate for the Google Ads API because there are additional restrictions to using them, and getting them to work generally takes significantly more effort than just generating a refresh token, which can be done in a few minutes. I don't understand why you wouldn't be able to use a refresh token.

That said, if you'd like me to take a look, can you provide more complete information about how you're specifying the authentication? There's some info about what's supported in the example config file: https://github.com/googleads/google-ads-ruby/blob/main/google_ads_config.rb#L37

Essentially, anything you provide here is just going to be passed through directly to the underlying code, so anything that the services support should work. Here's one example, but this is fundamentally the same for all services: https://github.com/googleads/google-ads-ruby/blob/main/lib/google/ads/google_ads/v10/services/ad_group_ad_service/client.rb#L325

noctivityinc commented 2 years ago

@mcloonan if Google provided us with instructions that worked on how to get a refresh token for an internal app that is running a script, I would, but right now I cant. Now we are getting:

"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."

With anything we do.

mcloonan commented 2 years ago

I can't say I'm familiar with that specific error. If you're having trouble generating a refresh token you can try reaching out to our general API support team here: https://groups.google.com/g/adwords-api

There's currently an issue with the desktop flow refresh token example in the Ruby library (the process changed and the example needs to be updated), which should be fixed next week. I would recommend once you figure out the issue behind that error that you use the OAuth playground to actually generate your token if the new auth examples aren't ready yet: https://developers.google.com/google-ads/api/docs/oauth/playground

noctivityinc commented 2 years ago

I just activated domain wide delegations and that seems to let me proceed. More examples of how to use this are very badly needed.

On Apr 29, 2022 at 1:34:59 PM, mcloonan @.***> wrote:

I can't say I'm familiar with that specific error. If you're having trouble generating a refresh token you can try reaching out to our general API support team here: https://groups.google.com/g/adwords-api

There's currently an issue with the desktop flow refresh token example in the Ruby library (the process changed and the example needs to be updated), which should be fixed next week. I would recommend once you figure out the issue behind that error that you use the OAuth playground to actually generate your token if the new auth examples aren't ready yet: https://developers.google.com/google-ads/api/docs/oauth/playground

— Reply to this email directly, view it on GitHub https://github.com/googleads/google-ads-ruby/issues/303#issuecomment-1113559325, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAATIAS2PMSI6NBOSUNHMRDVHQMUHANCNFSM44AD2UGQ . You are receiving this because you commented.Message ID: @.***>

noctivityinc commented 2 years ago

Thanks. You should know that I simply pasted:

gem 'google-ads-googleads’

Into bundler and it uses v10.0.0. In fact, I just did a bundle update and it said the version stayed the same, so not sure what the current version is or how to get it.

And there are not clear instructions on how to get a refresh token or the other credentials if you are simply doing backend server to server communication. Im not developing a web or desktop app, just a script for internal use.

On Apr 29, 2022 at 12:16:05 PM, mcloonan @.***> wrote:

The fix I made was after the 10.0.0 version of the library, so you should update to a more recent version which incorporates that fix. In fact, I don't believe 10.0.0 supports any modern version of the API, so you wouldn't be able to use it anyway.

Service accounts are not the preferred way to authenticate for the Google Ads API because there are additional restrictions to using them, and getting them to work generally takes significantly more effort than just generating a refresh token, which can be done in a few minutes. I don't understand why you wouldn't be able to use a refresh token.

That said, if you'd like me to take a look, can you provide more complete information about how you're specifying the authentication? There's some info about what's supported in the example config file: https://github.com/googleads/google-ads-ruby/blob/main/google_ads_config.rb#L37

Essentially, anything you provide here is just going to be passed through directly to the underlying code, so anything that the services support should work. Here's one example, but this is fundamentally the same for all services: https://github.com/googleads/google-ads-ruby/blob/main/lib/google/ads/google_ads/v10/services/ad_group_ad_service/client.rb#L325

— Reply to this email directly, view it on GitHub https://github.com/googleads/google-ads-ruby/issues/303#issuecomment-1113493346, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAATIATGMJ2TADC5UT33U7DVHQDMLANCNFSM44AD2UGQ . You are receiving this because you commented.Message ID: @.***>

mattparlane commented 2 years ago

Perhaps you had it in your Gemfile.lock? The latest version is 19.0.0: https://rubygems.org/gems/google-ads-googleads/versions/19.0.0

You can specify a version in your Gemfile thusly:

gem 'google-ads-googleads', '19.0.0'

(sorry if you know this, just trying to be helpful)