I work for a company that uses Google AdWords, and we have a .NET application (written in C#) that makes use of the Google AdWords API. We are using the latest version (201209) of the Google API client assemblies for .NET. The application currently uses the ClientLogin protocol for authenticating, but we are trying to migrate to OAuth 2.0.
I am fairly confident that I have gone through all of the required steps to be able to successfully negotiate a request for an authentication token. I am using the sample code solution that comes with the Google API client assemblies in order to test this, using the “Service Account” workflow. So far I have not succeeded. Within the code we call the GenerateAccessTokenForServiceAccount() method of the OAuth2Provider object that is the OAuthProvider property of an AdWordsUser object. The result is that a Google.Api.Ads.Common.Lib.AdsOAuthException is thrown with the message “Failed to get access to token for service account” that also includes a JSON object with one key-value pair:
“error” : “access_denied”
When examining the traffic using Fiddler2, I see what looks like a properly-formed request going out, according to the relevant documentation (https://developers.google.com/accounts/docs/OAuth2ServiceAccount) …
POST https://accounts.google.com/o/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: accounts.google.com
Content-Length: 583
Expect: 100-continue
Connection: Keep-Alive
grant_type=urn%3aietf%3aparams%3aoauth%3agrant-type%3ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzNDgzMjEzMjIyNDlAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCAic2NvcGUiOiJodHRwczovL2Fkd29yZHMuZ29vZ2xlLmNvbS9hcGkvYWR3b3Jkcy8iLCAiYXVkIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vb2F1dGgyL3Rva2VuIiwgImV4cCI6MTM1NzMzMTIxNSwgImlhdCI6MTM1NzMyNzYxNSwgInBybiI6IkluZm9zcGFjZUNvcnBAZ21haWwuY29tIn0.BnD3-oPozaUInI9LexIF_wqNnIOLeGLBfv1oJOjzpHjc9q5p_-Q7A7i_V3QkqCKgV2EmWT3wU8BNUKj7YrpKThWgzKNT661uA4HiF2ZPQNYduKxouJrB7OON9BXoWBdgkSjyWb5frEzTmzklM476SEQAJvWP2djxBSGaha3Qwww
… and a HTTP 400 response coming back that contains no meaningful header information, and the aforementioned JSON object in the body.
HTTP/1.1 400 Bad Request
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Date: Fri, 04 Jan 2013 19:26:54 GMT
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Content-Length: 31
{
"error" : "access_denied"
}
I am not sure what that response means. From what I’ve seen of other failed attempts described here and on other forums, I am assuming that the request is correctly formed and would normally succeed, but there is something in how the client access credentials are set up on the API console that is wrong enough to prevent an authentication token from being granted.
What follows is a step-by-step description of every step taken, from requesting the developer token to “access_denied”. It is my expectation that others who have gone before and succeeded will be able to identify whatever missteps I have made and offer sufficient information to get me past “access_denied”.
1. Using a Google AdWords MCC account, requested a developer token at the AdWords API Center. This request has been approved, and a developer token supplied.
2. For the same MCC account, logged in to the Google API Console (https://code.google.com/apis/console) and created a project (“API Project”). We did not register for a Project ID.
3. On the Services tab, we did not set up or activate any services. AdWords is not listed. According to the AdWords API documentation (https://developers.google.com/adwords/api/docs/authentication), this step can be skipped.
4. On the “API Access” tab of this project, we entered branding information and set up a Client ID for a Service account. This generated a “client ID” for a service account which had
a. a Client ID (012345678901.apps.googleusercontent.com)
b. an e-mail address (012345678901@developer.gserviceaccount.com)
c. a public key fingerprint (forty hexadecimal digits)
d. a private/public key (.P12 file), which we downloaded
5. I unzipped the code samples from the Google API client archive (awapi_dotnet_lib_15.2.0.zip) and opened the solution in Visual Studio 2012. I set the ConsoleTest project as the start project.
6. I uncommented and edited the relevant key-value pairs in the configuration file to set up the sample application to use the access credentials we had generated earlier.
<AdWordsApi>
<!-- Fill the header values. -->
<add key="UserAgent" value="Our_Application_Name"/>
<add key="DeveloperToken" value="hyP0tH3t1c47D3v370p3Rt0k3N"/>
<add key="ClientCustomerId" value="123-456-7890"/>
<!-- To use OAuth2 as authentication mechanism, uncomment the following section and comment the AuthToken and OAuth2 sections. -->
<add key="AuthorizationMethod" value="OAuth2" />
<!-- Use the following keys if you want to use client id and client secret.-->
<add key="OAuth2ClientId" value="012345678901.apps.googleusercontent.com" />
<add key="OAuth2ClientSecret" value="0123456789abcdef0123456789abcdef01234567" />
<!-- Use the following keys if you want to use a service account. -->
<add key="OAuth2ServiceAccountEmail"
value="012345...@developer.gserviceaccount.com" />
<add key="OAuth2PrnEmail" value="OurAdWordsMccAccountXYZ@gmail.com" />
<add key="OAuth2JwtCertificatePath"
value="C:\local_file_path\0123456789abcdef0123456789abcdef01234567-privatekey.p12" />
<add key="OAuth2JwtCertificatePassword" value="super_secret_password" />
</AdWordsApi>
7. In all cases, I’ve provided sample values rather than actual values. The ClientCustomerId value is actually the Customer ID of our Adwords MCC account. The OAuth2PrnEmail is the e-mail address of that account.
8. Even if the scope key-value pair isn’t set in the configuration file, the scope property in the AdWordsUser’s configuration does get set to the correct value for AdWords read/write access (https://adwords.google.com/api/adwords/) before an authentication token is requested. This is done by the call to AdWordsService.GetOAuthScope() in the first line of the method below.
9. In the sample console application from Google, the exception is thrown in the DoAuth2AuthorizationForServiceAccounts() method of the Program class in the code file Program.cs . The highlighted line is where the exception is thrown.
<span style="background: white; co...
Show original
/// <summary>
/// Does the OAuth2 authorization for service accounts.
/// </summary>
/// <param name="user">The AdWords user.</param>
private static void DoAuth2AuthorizationForServiceAccounts(AdWordsUser user)
{
user.Config.OAuth2Scope = AdWordsService.GetOAuthScope(user.Config as AdWordsAppConfig);
OAuth2Provider oAuth2 = new OAuth2Provider(user.Config);
user.OAuthProvider = oAuth2;
oAuth2.GenerateAccessTokenForServiceAccount();
}
That is the call that is supposed to get the authentication token from the AdWords API.
So far, in my investigations, in this forum and others, and in web searches, I have not yet seen an accounting from any other AdWords API user whose authentication requests have ended with the “access_denied” result, much less any advice on what to do when that happens. I have seen examples from people who have written their own code to generate a JWT and request authentication tokens, and I have seen inferences that one must activate at least one other Google API service in the API Console project before one can access the AdWords API. We would prefer to conduct all AdWords API operations through the API client assemblies that Google supplies, and would prefer not to associate our API client information with another API service, even if we don’t ever make use of it.
Did you manage to get this to work?I have the same problem and can't figure out how to solve it.I have followed the steps above for out Apps domain./Claus