Hi Anash, I tried that and it looks to have solved the problem :-)
many thanks for you help on this one Giles On Thursday, November 7, 2013 8:28:35 PM UTC, Anash P. Oommen (AdWords API Team) wrote: > > Hi Giles, > > I'll look at this a bit more closely later today, but I agree that the > problem is about your 40 threads all trying to refresh the access token at > the same time. The workaround would be to share the access token among the > various threads. > > A simple workaround would be to ensure that the AdsOAuthProvider is shared > among all the AdWordsUsers. Something like: > > AdWordsAppConfig config = new AdWordsAppConfig(); > // Set all the necessary property overrides here. > > AdsOAuthProvider provider = new OAuth2ProviderForApplications(config); > // Optional: Fetch an access token before initalizing the users > provider.RefreshAccessToken(); > > // Now create the users. Make sure you share the provider amongst them. > AdWordsUser user1 = new AdWordsUser(); > AdWordsUser user2 = new AdWordsUser(); > > user1.OAuthProvider = user2.OAuthProvider = provider; > > This way, the users won't race in the beginning to refresh access tokens > all at once. > > I'll make sure that this functionality is clearer / cleaner in a future > version of the client library. > > Cheers, > Anash P. Oommen, > AdWords API Advisor. > > On Tuesday, November 5, 2013 1:03:45 PM UTC-5, giles bodger wrote: >> >> Hi Anash, >> >> Our Windows service looks after all of our synching from AW, pushing >> updates to AW and downloading reports from AW. We have sql jobs that kick >> off these requests for all of our accounts multiple times per hour. >> Everything was working fine with Client Login - not to say that it wont >> with OAuth i am sure :) >> >> At the time of the errors, we would have been running up to 15 threads on >> Synch, 15 threads on Updates and 25 threads on Reports. Every request we >> make to the API has a new AdWordsUser object created as follows .... >> >> /* c# code START */ >> var adWordsUser = new AdWordsUser(); >> >> adWordsUser.Config.OAuth2ClientId = myConfig._oAuth2ClientId; >> adWordsUser.Config.OAuth2ClientSecret = myConfig._oAuth2ClientSecret; >> adWordsUser.Config.OAuth2RefreshToken = myConfig._oAuth2RefreshToken; >> >> return adWordsUser; >> /* c# code END */ >> >> .... >> (appreciate that i don't actually have to explicitly set these values as >> they are retrieved from the config at runtime) >> >> >> within each account synch or update push or report request, we call any >> or all of the following AW services ... >> >> ManagedCustomerService >> CampaignService >> BudgetService >> AdGroupService >> AdGroupAdService >> AdParamService >> CampaignCriterionService >> AdGroupCriterionService >> CustomerSyncService >> ReportUtilitiesService >> AdGroupBidModifierService >> FeedService >> FeedItemService >> FeedMappingService >> CampaignFeedService >> >> ...... >> >> We were at the AdWords workshop yesterday in London and brought this up >> during the OAuth presentation and Paul (cant remember his surname - too >> many Pauls!) said that it might be because we are creating a new >> AdWordsUser object for each request, and that this may have caused the >> library to have made too many refresh attempts ? >> >> As to how we are retrieving OAuth2 tokens, I have created a refresh token >> using the OAuthTokenGenerator.exe and am simply using this along with my >> ClientId and Secret within the configuration. My understanding from our >> conversation so far was that the actual access token is created and used >> under the hood by the client library and that the refresh token simply >> refreshes this token. >> >> Just as a side note - We also have a wrapper around all our requests to >> catch exceptions and to apply the necessary wait times if we are Rate >> Limited - however we have only been managing ACCOUNT and DEVELOPER scope >> levels of Rate Limit and not the USER level as we were getting with these >> particular Rate Limit exceptions. >> >> I know that the ClientId and Secret and Refresh Token do work because i >> can make requests of our production AW accounts from my local workstation >> with the same OAuth credentials that were failing - it appears to be the >> multiple threads of requests that we are getting stuck on. >> >> Many thanks in advance >> >> Giles >> >> >> >> >> >> >> On Tuesday, November 5, 2013 11:54:29 AM UTC, Anash P. Oommen (AdWords >> API Team) wrote: >>> >>> Hi Giles, >>> >>> The error suggests that you are refreshing the access token very >>> frequently (or rather, the library is doing this very frequently for some >>> reason). Could you provide more details on how your code works? Is it multi >>> threaded? Are you creating mutliple AdWordsUsers? How are you retrieving >>> OAuth2 tokens? Feel free to reply to author and ping this thread in case >>> you don't want to discuss some of these details in the public forum. >>> >>> Cheers, >>> Anash P. Oommen, >>> AdWords API Advisor. >>> >>> On Sunday, November 3, 2013 2:42:32 PM UTC-5, giles bodger wrote: >>>> >>>> Hi Anash, >>>> >>>> So we put our OAuth2 enabled application into our production >>>> environment, which caters for synching data, updating data and processing >>>> reports. We immediately ran into hundreds of the following errors ..... >>>> >>>> ........ >>>> >>>> <ExceptionType>Google.Api.Ads.Common.Lib.AdsOAuthException</ExceptionType> >>>> <StackTrace>An unhandled exception occurred. >>>> [Google.Api.Ads.Common.Lib.AdsOAuthException]: Failed to refresh access >>>> token. >>>> <HTML> >>>> <HEAD> >>>> <TITLE>User Rate Limit Exceeded</TITLE> >>>> </HEAD> >>>> <BODY BGCOLOR="#FFFFFF" TEXT="#000000"> >>>> <H1>User Rate Limit Exceeded</H1> >>>> <H2>Error 403</H2> >>>> </BODY> >>>> </HTML> >>>> >>>> >>>> Stack Trace: >>>> at >>>> Google.Api.Ads.Common.Lib.OAuth2ProviderForApplications.RefreshAccessTokenInOfflineMode() >>>> at Google.Api.Ads.Common.Lib.OAuth2ProviderBase.GetAuthHeader() >>>> at Google.Api.Ads.AdWords.Lib.AdWordsSoapClient.InitForCall(String >>>> methodName, Object[] parameters) >>>> >>>> ......... >>>> >>>> >>>> I thought from your explanation, that the access token is refreshed >>>> automatically - under the hood by the client library framework - when we >>>> supply the refresh token at run time - which is what i am doing. >>>> >>>> We have hit rate limit exceeded errors previously and have built in >>>> support to back off to not keep incurring them (appreciate that we don't >>>> incur a penalty for requests made when developer / account level usage is >>>> in breach) and making unnecessary requests. >>>> >>>> If you could shed any light on this I would be most appreciative >>>> >>>> many thanks in advance >>>> >>>> Giles >>>> >>>> >>>> >>>> On Tuesday, October 15, 2013 3:08:15 PM UTC+1, Anash P. Oommen (AdWords >>>> API Team) wrote: >>>>> >>>>> Hi Giles, >>>>> >>>>> That's a lot of questions, I'll try to get all your questions >>>>> answered. Feel free to follow up if you have more questions. >>>>> >>>>> At a low level, OAuth flow involves >>>>> (a) generating an authorization url >>>>> (b) Navigating the user to the url and asking user to authorize it. >>>>> (c) Obtaining an authorization code from server once the user >>>>> authorizes the access (This is the authorization code you see on the url) >>>>> (d) Exchanging the authorization code for an access token (for >>>>> authorizing your API calls, short lived, typically expires in 1 hour) and >>>>> optionally a refresh token (for obtaining a new access token once the old >>>>> one expires, won't expire until the user explicitly revokes this token) >>>>> (e) Making calls with access token in OAuth2 Authorization header. >>>>> (f) Detecting when the access token expires (either track >>>>> remaining lifetime of the token, or examine the errorcode thrown by the >>>>> server) >>>>> (g) Use refresh token to get a new access token, repeat (e) and (f) >>>>> >>>>> If you have just one customer, you can use OAuthTokenGenerator.exe to >>>>> do steps (a) to (d). If you have an application where users login >>>>> interactively, you need to implement (a) to (d) as shown in the OAuth >>>>> ASP.NET code example. The client library takes care of (e) to (g) >>>>> provided you mention the configuration in app.config or you load them >>>>> into >>>>> AdWordsUser at runtime. >>>>> >>>>> To answer your specific questions, >>>>> >>>>> 1. Yes, you are right in thinking that you can generate the >>>>> configuration one-time using OAuthTokenGenerator.exe and use that with >>>>> your >>>>> Windows service. >>>>> 2. No, it is used only for obtaining the access and refresh tokens. >>>>> 3. Yes, it is used to refresh the access token automatically once it >>>>> expires. Since your service is a Windows service, you will definitely >>>>> need >>>>> this token. >>>>> 4. ClientId and ClientSecret won't expire. Only access token will >>>>> expire. >>>>> 5. Yes, you can. >>>>> 6. Yes, you need to keep the project on the Google API Console in >>>>> tact, since the access and refresh tokens are issued against the Google >>>>> API >>>>> Console. >>>>> >>>>> Hope this helps. Let me know if you have more questions, >>>>> >>>>> Cheers, >>>>> Anash P. Oommen, >>>>> AdWords API Advisor >>>>> >>>>> On Tuesday, October 15, 2013 6:14:13 PM UTC+5:30, giles bodger wrote: >>>>>> >>>>>> Hi all, >>>>>> >>>>>> So we have a Windows Service which we use to manage our AdWords >>>>>> accounts and am now trying to convert to using OAuth2 from ClientLogin >>>>>> as >>>>>> the Authorization Method. >>>>>> The situation is such that I don't have a need to send a user to a >>>>>> redirect page to verify access to their data, I simply need MY Windows >>>>>> service to be able to access MY Adwords account data. >>>>>> >>>>>> reading up on the following page ...... >>>>>> >>>>>> https://code.google.com/p/google-api-adwords-dotnet/wiki/UsingOAuth#Adding_OAuth2_support_for_your_application_(multiple_logins) >>>>>> >>>>>> Because we have a hierarchy of Advertiser accounts all linked under >>>>>> a single master MCC, I think I am right in saying that I can create >>>>>> the necessary ClientID and the Client Secret by using the >>>>>> "OAuth2TokenGenerator.exe" application, and indeed I went through the >>>>>> following the steps...... >>>>>> >>>>>> 1. Navigated to the page https://code.google.com/apis/console/ >>>>>> 2. Log in to the adwords account >>>>>> 3. Create a new Project (although I don't really know what a >>>>>> project is or what it is for ?) >>>>>> 4. Then, not in the new "cloud console" dashboard but the old >>>>>> one, i was able to click on "API Access" and then "Create an OAuth2 >>>>>> client >>>>>> Id" >>>>>> 5. I then entered this data along with the already entered OAuth2 >>>>>> Scope in the OAuth2TokenGenerator >>>>>> 6. A browser window then opened to a localhost domain with the >>>>>> following url , >>>>>> http://localhost:8080/?code=[<http://localhost:8080/?code=4/SdZV4PkI8lbav1fOPSTdyHRzOZhr.Eg9_Y1PlO9seOl05ti8ZT3YR3M5ugwI>REMOVED >>>>>> >>>>>> FOR SECURITY PURPOSES] , I am presuming that this browser window >>>>>> opened in >>>>>> order for me to verify that i, as the adwords account user, will >>>>>> allow my >>>>>> windows service (that i am creating the OAuth2 configuration for) to >>>>>> have >>>>>> access to. As I was logged into adwords we had some sort of >>>>>> redirection and >>>>>> an Authentication Code "code" was given as you can see in the >>>>>> querystring. >>>>>> 7. The OAuth2TokenGenerator then presented me with the OAuth2 >>>>>> configuration that I will need >>>>>> >>>>>> >>>>>> <add key='AuthorizationMethod' value='OAuth2' /> >>>>>> <add key='OAuth2ClientId' value='[VALUE]' /> >>>>>> <add key='OAuth2ClientSecret' value='[VALUE]' /> >>>>>> <add key='OAuth2RefreshToken' value='[VALUE]' /> >>>>>> >>>>>> So I add these to my app.config, and then whenever I make a request >>>>>> via the Adwords API to access my account, I am creating the following >>>>>> AdWordsUser .... >>>>>> >>>>>> >>>>>> /* c# code START */ >>>>>> var adWordsUser = new AdWordsUser(); >>>>>> >>>>>> adWordsUser.Config.OAuth2ClientId = myConfig._oAuth2ClientId; >>>>>> adWordsUser.Config.OAuth2ClientSecret = myConfig._oAuth2ClientSecret; >>>>>> adWordsUser.Config.OAuth2RefreshToken = myConfig._oAuth2RefreshToken; >>>>>> // what is this used for ? >>>>>> >>>>>> return adWordsUser; >>>>>> /* c# code END */ >>>>>> >>>>>> >>>>>> So this then seems to work and I appear to be able to access the data >>>>>> in my Adwords account, which is great, but can I ask the following >>>>>> >>>>>> >>>>>> 1. Is this the correct method for setting up OAuth2 access to an >>>>>> Adwords account for use within a Windows Service? - I have no user >>>>>> other >>>>>> than myself that would need to verify that my Windows Service is >>>>>> allowed >>>>>> access to my Adwords account data. >>>>>> 2. Do I have any need for the Authorisation Code as given in the >>>>>> browser window as described in point 6 above as I explained the >>>>>> OAuth2TokenGenerator process ? >>>>>> 3. When I create my AdWordsUser object, do I need to utilise the >>>>>> OAuth2RefreshToken? Is this RefreshToken relevent to my set up? >>>>>> 4. Is my ClientId and ClientSecret about to expire at any point >>>>>> in the future, like an Access Token might expire with a mobile >>>>>> application >>>>>> style user access scenario? >>>>>> 5. We currently deploy more than one Windows Service to access >>>>>> the same Adwords account. Can more than 1 Windows service use these >>>>>> same >>>>>> credentials at the same time? >>>>>> 6. When logged into my account at >>>>>> https://code.google.com/apis/console/b/0/, I can see my "ClientId >>>>>> For Installed Applications" within which I see my Client ID and >>>>>> Client >>>>>> Secret - I also see RedirectURI's. Do I have any need for these? >>>>>> >>>>>> >>>>>> >>>>>> A lot of questions i know, so many thanks in advance >>>>>> >>>>>> Giles Bodger >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> -- -- =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ Also find us on our blog and discussion group: http://googleadsdeveloper.blogspot.com http://groups.google.com/group/adwords-api =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ You received this message because you are subscribed to the Google Groups "AdWords 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 "AdWords API Forum" group. To unsubscribe from this group and stop receiving emails from it, send an email to adwords-api+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.