OAuth with Google's AdWords API AuthenticationError

937 views
Skip to first unread message

baynezy

unread,
Mar 28, 2012, 10:39:13 AM3/28/12
to adwor...@googlegroups.com
I am trying (with not much luck) to access the Google AdWords API using the .Net Client Library to access their SandBox API.

Here is my code:-


            // create campaign
            var campaign = new Campaign
                               {
                                   name = "Simon's Campaign",
                                   status = CampaignStatus.ACTIVE,
                                   servingStatus = ServingStatus.SERVING,
                                   budget = new Budget
                                                {
                                                    period = BudgetBudgetPeriod.DAILY,
                                                    amount = new Money
                                                                 {
                                                                     microAmount = 100000
                                                                 },
                                                    deliveryMethod = BudgetBudgetDeliveryMethod.STANDARD
                                                },
                                   adServingOptimizationStatus = AdServingOptimizationStatus.OPTIMIZE,
                                   frequencyCap = new FrequencyCap
                                                      {
                                                          impressions = 100000,
                                                          timeUnit = TimeUnit.MINUTE,
                                                          level = Level.CAMPAIGN
                                                      }
                               };
            var operation = new CampaignOperation {@operator = Operator.ADD, operand = campaign};
            var operations = new CampaignOperation[1];
            operations[0] = operation;


            // get service
            var user = new AdWordsUser();
            var url = Request.Url.GetLeftPart(UriPartial.Path);
            var config = user.Config as AdWordsAppConfig;
            user.OAuthProvider = new AdsOAuthNetProvider(
                    config.OAuthConsumerKey,
                    config.OAuthConsumerSecret,
                    AdWordsService.GetOAuthScope(user.Config as AdWordsAppConfig),
                    url,
                    Session.SessionID
                );

            var service = (CampaignService) user.GetService(AdWordsService.v201109.CampaignService);
            var page = service.mutate(operations);

When I run this I get an `AdWordsApiException` with an InnerException `AuthenticationError.OAUTH_TOKEN_HEADER_INVALID @  Service[CampaignService.mutate]`

Now I have the following in my `Web.config`:-

    <!-- Note: For testing purposes, you can use the OAuth consumer key/secret as anonymous/anonymous.-->
    <add key="AuthorizationMethod" value="OAuth"/>
    <add key="OAuthConsumerKey" value="anonymous"/>
    <add key="OAuthConsumerSecret" value="anonymous"/>
    <!-- Uncomment this key if you want to use v13 sandbox. -->
    <!-- <add key="LegacyAdWordsApi.Server" value="https://sandbox.google.com"/> -->
    <!-- Uncomment this key if you want to use AdWords API sandbox. -->
    <add key="AdWordsApi.Server" value="https://adwords-sandbox.google.com"/>

As I understand it this is set up correctly, what am I missing?

Any help would be very gratefully received!!!

Anash P. Oommen

unread,
Mar 29, 2012, 5:04:12 AM3/29/12
to adwor...@googlegroups.com
Hi Simon,

There are couple more pieces to getting OAuth to work on an ASP.NET website.

1. There's some initialization code that should go in your Global.asax. :  http://code.google.com/p/google-api-adwords-dotnet/source/browse/trunk/examples/adwords/csharp/oauth/Global.asax.cs 
2. There should be some mechanism to trigger the OAuth signup, as shown here:

Hope this helps: Let me know if you have more questions.

Cheers,
Anash P. Oommen,
AdWords API Advisor.

baynezy

unread,
Mar 29, 2012, 7:01:31 AM3/29/12
to adwor...@googlegroups.com
Anash,
Thanks very much for your help on this. I think I have gone down the
wrong path here. The OAuth version of the API presents me with a
CAPTCH challenge that I need to forward to the user. However, I am not
creating a client application for users to manage their AdWords
accounts where this process makes perfect sense as I would not want to
store their account credentials. However, I am building an integration
with my application so I can programmatically create campaigns,
adgroups, etc. and this CAPTCHA challenge makes this not feasible as
this will not be in response to a user action but an automated
process. Is there a way to interact with the API where I can use my
credentials that I know, without having to deal with manually
authenticating?

Thanks again.

Simon Baynes 

Anash P. Oommen

unread,
Mar 29, 2012, 7:20:14 AM3/29/12
to adwor...@googlegroups.com
Hi Simon,

AFAIK, OAuth doesn't present a Captcha challenge, ClientLogin API does. Sounds like a misconfiguration to me. OAuth 1.0a access tokens don't expire, so you need to get the user to enter the credentials once to generate an accessToken, save it, and then keep reusing it for future requests. The other option is to link the client account under your MCC, and use your credentials to generate AuthTokens. That way, you won't have to ask for your client's credentials at all, but the linking process is manual.

Could you provide some more details of your application? E.g. is it a web application?

Cheers,
Anash P. Oommen,
AdWords API Advisor.


baynezy

unread,
Mar 29, 2012, 7:51:25 AM3/29/12
to adwor...@googlegroups.com
Anash,
Again thank you for your quick response. I am building a web application that when new items are added to our system we can potentially automatically add a new Campaign to the our AdWords account and then subsequently new AdGroups, Ads and Keywords. I am at the early stages really learning the capabilities of the API and I am having a few problems getting going. I downloaded the the .Net client library from here http://code.google.com/p/google-api-adwords-dotnet/ and I am using that as the basis of starting my own proof of concept project. Mainly my issues are compounded by the fact that all the examples I can find are a mix of different versions and so I am a little unclear on how to get going.

I think what I really need help with is how to get the AdWordsUser authenticated in a way that I can the access the API from then on with no challenge. I have no requirement to use OAuth as this will be an internal service using just our company AdWords account.

What I have so far is based on a combination of this Java example http://code.google.com/apis/adwords/docs/first-request.html and this article you wrote http://code.google.com/p/google-api-adwords-dotnet/wiki/HowToUseAdWordsUser

Here is my code:-

public ActionResult Create()
{
var headers = new Dictionary<string, string>
              {
              {"CompanyName", "MyCompany.com"},
{"Email", "mye...@gmail.com"},
{"Password", "password"},
{"DeveloperToken", " myemail @gmail.com++USD"}
              };
var user = new AdWordsUser(headers);
var service = (CampaignService)user.GetService(AdWordsService.v201109.CampaignService, "https://sandbox.google.com");
var budget = new Budget
{
period = BudgetBudgetPeriod.DAILY,
amount = new Money(),
deliveryMethod = BudgetBudgetDeliveryMethod.STANDARD
};

var campaign = new Campaign
  {
  name = "Simon Campaign",
  status = CampaignStatus.PAUSED,
  biddingStrategy = new ManualCPC(),
  budget = budget
  };
var operation = new CampaignOperation {operand = campaign, @operator = Operator.ADD};
var operations = new[] { operation };
var result = service.mutate(operations);

return View();

This is an ASP.NET MVC 3 web application, when executing the code above I get an AuthTokenException. When I dig into the error it is because I am getting an System.Net.WebException {"The remote server returned an error: (403) Forbidden."}. I get exactly the same response when I remove the second argument from the GetService call on AdWordsUser.

If you could point me in the right direction I would be eternally grateful.

Anash P. Oommen

unread,
Mar 29, 2012, 8:27:07 AM3/29/12
to adwor...@googlegroups.com
Hi Simon,

I see... let's get a code example running in that case...

The easiest approach is as follows:

1. Make sure your Web.config looks exactly as follows: http://code.google.com/p/google-api-adwords-dotnet/source/browse/trunk/examples/adwords/csharp/App.config. In case you have other stuff in your Web.config, you need to merge the two.

2. Enter your MCC email, password, clientCustomerId, developerToken in your Web.config.
3. In your code, do

AdWordsUser user = new AdWordsUser();// this loads all configs from your Web.Config
CampaignService service = (CampaignService) user.GetService(AdWordsService.v201109.CampaignService);
// Build your campaign, operation, do service.mutate(). Refer to the examples folder in the downloaded zip for various code examples.

4. Run your website. If you face any issues, let me know, along with the error you are facing.

Cheers,
Anash

Anash P. Oommen

unread,
Mar 29, 2012, 8:32:16 AM3/29/12
to adwor...@googlegroups.com
Hi Simon,

Almost forgot to mention: since you are making calls to the sandbox, you need to initialize the sandbox and use the clientCustomerIds in it.

1. In your Web.config, you should have email/password as your gmail email/password. Comment out clientCustomerId.
3. Call GetAccountHiearchy.cs. Example here:  http://code.google.com/p/google-api-adwords-dotnet/source/browse/trunk/examples/adwords/csharp/v201109/AccountManagement/GetAccountHierarchy.cs. This will return the sandbox accounts that were created for you.
4. Copy one of those customerIds into your web.config's clientCustomerId key, and uncomment the key.
5. Run any code example.

Anash

baynezy

unread,
Mar 29, 2012, 11:53:29 AM3/29/12
to adwor...@googlegroups.com
Anash,
Thanks very much this is starting to come together. I have set up the Web.config as requested and I am trying to run http://code.google.com/p/google-api-adwords-dotnet/source/browse/trunk/examples/adwords/csharp/v201109/BasicOperations/GetCampaigns.cs. I am adding adding a command line argument of 'v201101.GetAllCampaigns' as you specify in your YouTube video http://www.youtube.com/watch?v=XRqbqtsGO_g&feature=player_embedded. However, every time I run it it just list the help text to the console. It is like it does not see he command line arguments. I also compiled the exe and ran it from the command line with 'v201101.GetAllCampaigns' and it also just outputs the help text. It is like I am having a bad brain moment, and cannot see why this is failing. I would appreciate some thoughts on what I am doing wrong if you can think of something obvious.

Anash P. Oommen

unread,
Mar 30, 2012, 12:30:45 AM3/30/12
to adwor...@googlegroups.com
Hi Simon,

v201101 got sunset last month. Try v201109.GetCampaigns as the command line version. (Or in general, apiversion.codeexamplename as command line argument). I'll update the video appropriately or leave comments on the youtube video.

Cheers,
Anash

baynezy

unread,
Mar 30, 2012, 4:25:49 AM3/30/12
to adwor...@googlegroups.com
Anash,
Thanks for your tip. I have v201109.GetCampaigns running now but I am getting a Google.Api.Ads.Common.Lib.AuthToekException AuthToken login failed, This was caused by a System.Net.WebException (The remote server returned an error: (403) Forbidden.)

I also tried it with the <add key="AdWordsApi.Server" value="https://adwords-sandbox.google.com"/> uncommented and I get the exact same error.

Here is the contents of my App.config file:-


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="AdWordsApi" type="System.Configuration.DictionarySectionHandler"/>
  </configSections>
  <AdWordsApi>
    <!-- Change the appropriate flags to turn on SOAP logging. -->
    <add key="LogPath" value="C:\Logs\"/>
    <add key="LogToConsole" value="false"/>
    <add key="LogToFile" value="false"/>
    <add key="MaskCredentials" value="true"/>
    <add key="LogErrorsOnly" value="false"/>

    <!-- Set the service timeout in milliseconds. -->
    <!-- <add key="Timeout" value="100000"/> -->

    <!-- Fill the following values if you plan to use a proxy server.-->
    <add key="ProxyServer" value=""/>
    <add key="ProxyUser" value=""/>
    <add key="ProxyPassword" value=""/>
    <add key="ProxyDomain" value=""/>

    <!-- Use this key to change the default timeout for Ads services
        (in milliseconds.)-->
    <add key="Timeout" value="100000"/>

    <!-- Use this key to enable or disable gzip compression in SOAP requests.-->
    <add key="EnableGzipCompression" value="true"/>

        <!-- Fill the header values. -->
        <add key="UserAgent" value="INSERT_YOUR_COMPANY_OR_APPLICATION_NAME_HERE"/>
        <!-- <add key="ClientEmail" value="INSERT_YOUR_CLIENT_EMAIL_HERE"/> -->
        <add key="DeveloperToken" value="mye...@gmail.com++USD"/>
        <!-- Uncomment this key and comment ClientEmail if you want to specify
         customer id instead of customer email.
        <add key="ClientCustomerId"
                 value="INSERT_YOUR_CLIENT_CUSTOMER_ID_HERE"/> -->
        <!-- Application token is now optional and will be ignored by the server.-->
        <!-- <add key="ApplicationToken"
             value="INSERT_YOUR_APPLICATION_TOKEN_HERE"/> -->

    <!-- Set the Authorization method to be used with the client library. -->
    <!-- To use ClientLogin as authentication mechanism, uncomment the following
         section and comment the OAuth section below. -->
        <add key="AuthorizationMethod" value="ClientLogin" />
        <add key="Email" value="mye...@gmail.com"/>
        <add key="Password" value="my actual password for my gmail account"/>
        <!-- Optional: uncomment this if you want to reuse an authToken multiple
         times. -->
    <!-- <add key="AuthToken" value="INSERT_YOUR_AUTH_TOKEN_HERE"/> -->

    <!-- To use OAuth as authentication mechanism, uncomment the following
         section and comment the AuthToken section above. -->

    <!-- Note: For testing purposes, you can use the OAuth consumer key/secret
         as anonymous/anonymous.-->
    <!--

    <add key="AuthorizationMethod" value="OAuth" />
    <add key="OAuthConsumerKey" value="INSERT_YOUR_OAUTH_CONSUMER_KEY_HERE" />
    <add key="OAuthConsumerSecret"
         value="INSERT_YOUR_OAUTH_CONSUMER_SECRET_HERE" />

    -->

    <!-- Uncomment this key if you want to use v13 sandbox. -->
    <!-- <add key="LegacyAdWordsApi.Server"
             value="https://sandbox.google.com"/> -->

    <!-- Uncomment this key if you want to use AdWords API sandbox. -->
    <!-- <add key="AdWordsApi.Server" value="https://adwords-sandbox.google.com"/> -->
  </AdWordsApi>
  <system.web>
    <webServices>
      <soapExtensionTypes>
        <add type="Google.Api.Ads.Common.Lib.SoapListenerExtension, Google.Ads.Common"
             priority="1" group="0"/>
      </soapExtensionTypes>
    </webServices>
  </system.web>
  <system.net>
    <settings>
      <httpWebRequest maximumErrorResponseLength="-1"  />
    </settings>
  </system.net>
</configuration>

Thanks for your continued help on this!!!!

baynezy

unread,
Apr 2, 2012, 4:59:17 AM4/2/12
to adwor...@googlegroups.com
Anash,
Thanks very much for your help on this. I think I have solved the problem, I think it is because my Gmail account has the 2-legged authentication turned on. I am using a different account now and it is now working.

Thanks.

Simon

Anash P. Oommen

unread,
Apr 2, 2012, 9:11:27 AM4/2/12
to adwor...@googlegroups.com
Hi Simon,

Nice to know. If you have 2-legged authentication turned on, then you need to generate an application-specific password as discussed at http://adwordsapi.blogspot.com/2011/02/authentication-changes-with-2-step.html.

Cheers,
Anash P. Oommen,
AdWords API Advisor.

Chirag

unread,
May 24, 2012, 12:13:26 PM5/24/12
to adwor...@googlegroups.com
Hello All,

Any special configuration required for Running OAuth 1.0a running succesfully?
I am trying to run one of my report download code, but it is giving error :

Error Message: <eye3-stackless title='AuthServer User Error OAUTH_TOKEN_HEADER_INVALID'/> AuthenticationError.OAUTH_TOKEN_HEADER_INVALID @ ; trigger:'<null>'; errorDetails:message=Invalid Header Service[ReportInfoService.get]

Please note : It is only has error from few server only. This same file is working on my localhost setup and also from two of my server.

Thanks,
chirag
Reply all
Reply to author
Forward
0 new messages