PHP pass credentials dynamically (not through adsapi_php.ini)

1,192 views
Skip to first unread message

Tim Johnson

unread,
Aug 25, 2017, 2:42:38 PM8/25/17
to AdWords API Forum
Hi Support,

As my application will be supporting users from multiple MCC accounts, I would prefer to not have to hardcode authentication credentials in the adsapi_php.ini to authenticate requests (as suggested in the documentation). Instead, I would like to pass the token/other credentials as an argument to into a function.  I know you don't support REST, but is there an easier way to authenticate requests than having to write to a .ini file and then pass that through?

Thanks,
Tim

Shwetha Vastrad (AdWords API Team)

unread,
Aug 25, 2017, 3:08:18 PM8/25/17
to AdWords API Forum
Hi Tim, 

If you would prefer not to use the adsapi_php.ini file to store the OAuth2 credentials, you can use the OAuth2TokenBuilder and AdWordsSessionBuilder to set the same information. If you interested in using web-flow OAuth2 credentials, you can follow this guide to set up authentication. 

Regards,
Shwetha, AdWords API Team.

Tim Johnson

unread,
Aug 25, 2017, 9:21:12 PM8/25/17
to AdWords API Forum
Hi Shwetha,

Thanks for the link but I do not think this addresses my question as that guide doesn't address to how pass through the token if you already have it.  Also, it appears this information still needs to be hard-coded into PHP files.  I have built the token, I have the .json file (could be anything though) but now want to make calls.  

So for example, in the doubelclick API you have a clear way to set the token:
$client = new Google_Client();
$client->setaccesstoken($token);

where $token is the json that google returns when getting the token request.

Happy to clarify if needed.

Regards,
Tim

Shwetha Vastrad (AdWords API Team)

unread,
Aug 28, 2017, 12:31:27 PM8/28/17
to AdWords API Forum
Hi Tim, 

You need to use OAuth2TokenBuilder and AdWordsSessionBuilder to pass the values programmatically. 

    $oAuth2Credential = (new OAuth2TokenBuilder())
     
->withClientId("OAUTH_2_CLIENT_ID")
     
->withClientSecret("OAUTH_2_CLIENT_SECRET")
     
->withRefreshToken("REFRESH_TOKEN")
     
->build();

   
// Construct an API session configured from the OAuth2 credentials above.
    $session
= (new AdWordsSessionBuilder())
       
->withDeveloperToken("DEVELOPER_TOKEN")
       
->withOAuth2Credential($oAuth2Credential)
       
->withClientCustomerId("CLIENT_CUSTOMER_ID")
       
->build();


The first section builds OAuth2 access token fetchers, which will get access tokens as and when required. You need to use the oAuth2Credential object when you build a AdsSession in the PHP client library. I hope this helps. If you have any further questions, I would suggest that you post on the library's issue tracker so the library owners can help you out. 

Jean-Fabrice Rabaute

unread,
Jan 7, 2018, 1:44:44 PM1/7/18
to AdWords API Forum
Hi,

I'm working on migrating from the old api to the new one and I don't understand how to reuse the "access_token".

When using OAuth2TokenBuilder and AdWordsSessionBuilder, I can set the "refresh_token" but not the "access_token".
If I understand correctly, setting only the refresh_token will force to get a new access_token everytime I create a new instance of OAuth2TokenBuilder (which is instantiating a UserRefreshCredentials object when the ->build() method is called in my case).
This probably works (not sure there might be race condition with multiple requests in // and then one access_token might be invalid), but this means that an access_token will be fetched everytime, so two http requests instead of one.
When I have an access_token which is valid for 3600 seconds, I'd like to be able to reuse it for the valid period, but I can't as there is no method in OAuth2TokenBuilder nor UserRefreshCredentials to set the "access_token" when I instantiate my objects on new client http requests.

In your response, you say "The first section builds OAuth2 access token fetchers, which will get access tokens as and when required". But how can this happen if the access_token is not provided? As it is not provided, a new http request needs to be done to get one before doing the adwords api request, right?

In the old API, passing the "refresh_token" AND "access_token" was done when instantiating the AdwordsUser object (here: https://github.com/googleads/googleads-php-lib/blob/deprecated/src/Google/Api/Ads/AdWords/Lib/AdWordsUser.php#L92 ). It was then possible to reuse an existing and still active "access_token".
Now, I really can't see how to reuse an existing "access_token" with the new api, only the "refresh_token".

Am I missing something?

Thank you for any help/feedback.

PS: My next problem is to detect that those object are effectively refreshing the access_token because I'd like to update/save/cache the new one to be able to reuse it again for the active time period (usually one hour). That will probably be my next question. The new api seem very weird in this regard. The google/google-auth-library-php (which is used by the adwords library) seem to have the same problem (The app is unable to get/cache/manage the access_token in an easy way).

Jean-Fabrice Rabaute

unread,
Jan 7, 2018, 2:18:58 PM1/7/18
to AdWords API Forum
This github issue seems related to the problem I have: https://github.com/googleads/googleads-php-lib/issues/180

The answer seems to imply that an OAuth2 object should be instantiated and not use the OAuth2TokenBuilder (There is a way to set access_token with OAuth2 but not with OAuth2TokenBuilder). But still, the app has no way to synchronize the access_token refresh part, which is important in a distributed system as multiple instances of php on different servers can refresh the access token at the same time and I'd like to have a way to synchronize the refresh here. (My app was taking care of this before, using a redis distributed lock mechanism so I was in control of refreshing and updating/saving the new access_token).

I'm wondering if having my own object implementing the "FetchAuthTokenInterface" is the solution here. This seems a bit complex but maybe this is the way to go?

Thanks.

Vincent Racaza (AdWords API Team)

unread,
Jan 8, 2018, 12:00:59 AM1/8/18
to AdWords API Forum
Hi Jean,

If you are using our client libraries, you don't need to manually set the access token in your request as the library itself is generating an access token in the background using your refresh token. If your access token is about to expire or has already expired, the client library will automatically generate a new access token using the refresh token.

About setting or reusing the access token, this is already incorporated in the client libraries, and you don't need to do this manually. There is also no method currently that would manually set the access token in your request. If you want to reuse your access token for your separate requests, then you can use the refresh token instead as this is linked to your access token at a time.

Also, if you are not using our client libraries, you can refer to the generic OAuth2 guide. The guide provides a step by step instructions on how to authenticate via the authentication type of your choice. For example, if you will be authenticating via the "Installed application" type, it provides the whole steps on how to generate the refresh and access tokens and how to call an API method via HTTP or CURL request.

If you have further clarifications on this, I suggest that you create a new forum thread so we can better track your concern.

Thanks,
Vincent
AdWords API Team

Jean-Fabrice Rabaute

unread,
Jan 8, 2018, 12:34:36 AM1/8/18
to AdWords API Forum
Hi Vincent,

Thank you for your answer.
I have added more questions inline.
For info, I'm using the public google adwords php library.


Le dimanche 7 janvier 2018 21:00:59 UTC-8, Vincent Racaza (AdWords API Team) a écrit :
Hi Jean,

If you are using our client libraries, you don't need to manually set the access token in your request as the library itself is generating an access token in the background using your refresh token.

What does "generating" means here? I've tried, and in my case, it means an http request to get a new access token. It means that it's slow because almost every query to the adwords api is from a newly instantiated AdwordsSessionBuilder so there is no access token. So every time my web app is getting a client call and instantiating the object, and querying adwords api on behalft of the client, two synchronous calls will be done: one to get a valid access token, one for the real query.


 
If your access token is about to expire or has already expired, the client library will automatically generate a new access token using the refresh token.

About setting or reusing the access token, this is already incorporated in the client libraries, and you don't need to do this manually.

How can the library do this when it does not know anything about the environment it's working on? When a system is distributed (having multiple instances of the web app running on different machines and load-balanced), how can the php library itself share and synchronize a common resource between the instances?


It seems pretty clear to me that it's the application responsibility to cache/share/synchronize the token on a distributed app design.

Am I missing something? If so, can you point me to the code in the adwords php library which takes care of caching the access_token on distributed environments?
 
There is also no method currently that would manually set the access token in your request. If you want to reuse your access token for your separate requests, then you can use the refresh token instead as this is linked to your access token at a time.

Yes, that works, but it's means adding a preliminary http request every time, which is not optimal.
 

Also, if you are not using our client libraries, you can refer to the generic OAuth2 guide. The guide provides a step by step instructions on how to authenticate via the authentication type of your choice. For example, if you will be authenticating via the "Installed application" type, it provides the whole steps on how to generate the refresh and access tokens and how to call an API method via HTTP or CURL request.

If you have further clarifications on this, I suggest that you create a new forum thread so we can better track your concern.

Thanks,

Thanks.
 
Vincent
AdWords API Team

Josh Radcliff (AdWords API Team)

unread,
Jan 8, 2018, 9:06:33 AM1/8/18
to AdWords API Forum
Hi Jean,

I'm going to send this over to our PHP client library expert. Since your questions revolve around the details of that library, you may want to open an issue on Github so we can track this under the library's issue tracker.

Thanks,
Josh, AdWords API Team

Thanet Knack Praneenararat (AdWords API Team)

unread,
Jan 9, 2018, 10:53:29 AM1/9/18
to AdWords API Forum
Hello Jean,

Nice to meet you. I'm an owner of the googleads-php-lib.
I'm still following up all your conversation with my colleagues but from what you said in this thread,

The google/google-auth-library-php (which is used by the adwords library) seem to have the same problem (The app is unable to get/cache/manage the access_token in an easy way).

Have you confirmed with the owner of that library already?
And as you clearly see through this, as the googleads-php-lib depends on the google-auth-library-php library, if that library really doesn't support what you want, I'm afraid our library doesn't support it as well.

I'll come back when I finish following up all the conversations.

Best,
Thanet, AdWords API Team

Jean-Fabrice Rabaute

unread,
Feb 2, 2018, 12:05:45 AM2/2/18
to AdWords API Forum
Hi,

Sorry for the delay.

I solved my problem by implementing "FetchAuthTokenInterface" interface and passing my implementation to "AdWordsSessionBuilder::withOAuth2Credential".
The token refresh is now handled by my object and I can synchronize and use my custom caching as well the way I want.

I don't know if this is the correct way to do it or if there is a more "official" way to do so.

Thanks.

Thanet Knack Praneenararat (AdWords API Team)

unread,
Feb 2, 2018, 1:06:33 PM2/2/18
to AdWords API Forum
Hello,

Looking into this again, isn't the getOrFetchAccessToken method in OAuth2TokenRefresher similar to what you need?
It can fetch a new access token when needed but will just return the existing one if it's not expired yet.

Best,
Thanet, AdWords API Team

Jean-Fabrice Rabaute

unread,
Feb 2, 2018, 3:48:06 PM2/2/18
to AdWords API Forum
From what I understand this wouldn't work.

I see the following problem with getOrFetchAccessToken in a distributed environment:

Let's say I have two servers with the php code answering requests from clients, server A and server B.

Those two servers can receive a request at the same time. As they are isolated if getOrFetchAccessToken needs to refresh the token, each server will refresh the token and get an access_token.
This should not happen and the "refresh token" task should be synced (with a distributed lock system like redis/zk/etcd) between servers so only one is actually refreshing the token, updating the db or cache and the other ones are getting the new value from the updated cache.
This is all app dependent (well, more client infra-dependent stuff) so the googleads-php-lib cannot/shouldn't deal with this and it should just provide the necessary hooks so the app can take care of this.
This is what I'm doing with the custom FetchAuthTokenInterface implementation I have.

Note about "shouldFetchAccessToken". Calling "shouldFetchAccessToken" does not help even within the same request.
I can call "shouldFetchAccessToken" and it will return false and the next call will return "true".
It means that when calling getOrFetchAccessToken I don't know if the value returned is the "cached" one (whatever that means as cache should be done by the app anyways) or a refreshed one, so I wouldn't know when to save it (well, I could compare with the one I had previously that would work). But then, getOrFetchAccessToken has the problem described initially.

I hope it makes sense.

Thanks.

Thanet Knack Praneenararat (AdWords API Team)

unread,
Feb 5, 2018, 6:27:50 AM2/5/18
to AdWords API Forum
Hello Jean,

From your narrated use case, I agree that what you've done is probably the best right now.
Thanks for your time describing your use case so it can benefit other people too.

Best,
Thanet, AdWords API Team

Suraj Nayak

unread,
Jul 9, 2018, 5:27:04 AM7/9/18
to AdWords API and Google Ads API Forum
Thanks Shwetha , its been a great help.

rob...@adbud.io

unread,
Nov 7, 2018, 6:17:58 AM11/7/18
to AdWords API and Google Ads API Forum
Hello
Im about to start using the php-library after 10 years of Adwords Api the native style.
But I am not able to find out how to share my credentials (including access token).
When I read this thread I get the feeling that it is not a common use case, but when I read Google Ads-docs its strongly recommended doin this if there is many processes running at the same time.

”In multiprocess or distributed apps, sharing the credential requires you to persist it. To ensure multiple processes or servers don't attempt to refresh the credential at the same time (resulting in excessive refresh requests), we advise proactively refreshing the credential in a central place and sharing it across processes/servers.”

https://developers.google.com/adwords/api/docs/guides/authentication

I am storing the credentials in the db and refresh the access token every 15 minutes from a central cronjob. So I just want to fetch it and inject it into the library in every thread.
Is there a way to accomplish this with the googleads/googleads-php-lib-library?

Or do we still have to extend it like Jean did?

Best regard Robert

Teja Makani

unread,
Nov 7, 2018, 12:29:32 PM11/7/18
to AdWords API and Google Ads API Forum
Hello Robert,

The solution described by Jean seems to be the best option for you based on your requirement.

Regards,
Sai Teja, AdWords API Team.
Reply all
Reply to author
Forward
0 new messages