Using OAuth with the AdWords API

in AdWords API

This article provides a tutorial introducing the use of OAuth 2.0 in AdWords API applications. The AdWords API had had full support for OAuth since 2011, and several customers have asked me for ways to authenticate users for the API without needing to supply username and passwords; OAuth provides a solution to this problem.

In this tutorial, I'll outline support for OAuth in the AdWords API, explain the basic OAuth 2.0 authentication flow, guide you through the sign-up process required for using OAuth 2.0 with Google APIs, then I'll present some example code to get you started requesting, using, validating, refreshing, and revoking tokens. If you need a broader introduction to Google API authentication, then you could also check out my higher-lever overview of AdWords API Authentication.

AdWords API OAuth Support

The AdWords API currently supports version 1.0a and version 2.0 of the OAuth specification: v1.0a requires requests to be signed, which is a hassle that's not required in v2.0; however, v2.0 requires you to register your application with Google, which is optional in v1.0a. An additional problem with v1.0a is that it's been deprecated using the same schedule as the ClientLogin API, so it's best to use v2.0.

An older version of this tutorial covered OAuth 1.0a as it was the only version implemented for AdWords at the time; however, I've now updated it to use v2.0, which means you'll need to register your tool before you begin. I'll cover that in the next section, then move on to an example of implementing oAuth 2.0 in PHP.

Basic OAuth Authentication Flow

OAuth works by replacing the normal username and password combination that's required for logging into an account with an identification token; you send the user to a page on Google where they sign into their account and authorize your application, then they are redirected back to your website with an access token that you can use to call the AdWords API.

While using the AdWords API with the ClientLogin API also requires an access token, you need to exchange a username and password for it, and thus need to store these for future use when the token expires; however, with OAuth you can obtain a refresh token that can be stored and used to request a new access token when it expires, without needing to store a user's credentials.

OAuth API Parameters

In addition to the access and refresh tokens described above, you also need tokens that identify your application to make calls to the OAuth API; there are some additional options that are often useful. For reference, here's a list of the parameters used in this tutorial:

  • Access Token – Grants your tool access to use a Google account with the AdWords API for a limited period of time.
  • Refresh Token – Enables your software to generate a new access token once the access token has expired.
  • Client ID – Informs the OAuth API which application is making requests to it.
  • Client Secret – Provides an additional layer of security when identifying your tool.
  • Redirect URI – Specifies the URL that you would like users to be sent to once they've given consent—or not—for your application to access their account.
  • Authorization Code – Gives your tool permission to request access and refresh tokens once the user has approved your request.
  • Error Code – Indicates that the user rejected your authorization request.
  • Response Type – Requests an authorization code instead of just generating an access token.
  • State – Passes a value—such as a user ID—back to your application, so it can continue the sign up process.
  • Scope – Determines which services—AdWords, Google Analytics, GMail etc—within in a Google account that your tool is allowed to access.
  • Approval Prompt – Changes the default behaviour of automatically approving your application if the OAuth sequence is run multiple times.

Much of the complexity of using OAuth is hidden within the AdWords API client libraries, but you will need to know how to register your application and redirect URI to obtain a client id and secret, use the id and secret to obtain an authorization code, use the authorization code to obtain access and refresh tokens, persist the tokens for later use, call the AdWords API using your tokens, use the refresh token to generate a new access token when needed, and how to deal with and error conditions that arise.

It is also useful to know how to use the state parameter to link OAuth into the larger process of signing up a user for your service and persisting their tokens, request access to other services—such as Google Analytics—at the same time as AdWords using the scope parameter, revoke access to an account so your application can clean up after it's finished, and maybe how to re-prompt the user for consent if they run through the OAuth process more than once.

Swapping an Authorization Code for Access and Refresh Tokens

Once the user has granted you access to their account, they will be redirected to your redirect URL with a parameter, called code, containing the authorization code; the following code will pick up this parameter and request your tokens:

<?php
 
require_once 'Google/Api/Ads/AdWords/Lib/AdWordsUser.php';
 
$clientId = "YOUR_CLIENT_ID";
$clientSecret = "YOUR_CLIENT_SECRET";
$callbackUrl = "YOUR_REDIRECT_URL";
 
// Create a new user and set the oAuth settings
$user = new AdWordsUser();
$user->SetOAuth2Info(array(
    "client_id" => $clientId,
    "client_secret" => $clientSecret
));
 
$authCode = $_REQUEST["code"];
$user->GetOAuth2AccessToken($authCode, $callbackUrl);
?>
Requesting Access and Refresh Tokens

This code is pretty much the same as the authorization code example above, but it's now using the GetOAuth2AccessToken() method to request the full access and refresh tokens: This method takes the authorization code extracted from the request and the same callback URL you used earlier, then obtains the tokens from the OAuth API and stores them in the AdWordsUser object.

Saving Your Access and Refresh Tokens

If you intend to use the access token for more than a single request to the AdWords API, you'll need to persist them for later use. To keep this tutorial simple I'm just going to persist the tokens into a file; the following function does that given an AdWordsUser and the name of a target file:

function saveAuth($user, $filename) {
    $oauthInfo = $user->GetOAuth2Info();
    $clientId = $oauthInfo["client_id"];
    $clientSecret = $oauthInfo["client_secret"];
    $accessToken = $oauthInfo["access_token"];
    $refreshToken = $oauthInfo["refresh_token"];
    $timestamp = isset($oauthInfo["timestamp"]) ? $oauthInfo["timestamp"] : 0;
    $expiresIn = isset($oauthInfo["expires_in"]) ? $oauthInfo["expires_in"] : 0;
    file_put_contents(
        $filename, 
    "$clientId\n$clientSecret\n$accessToken\n$refreshToken\n$timestamp\n$expiresIn"
    );
}
A Function for Saving OAuth Tokens

This function uses the GetOAuth2Info() method to obtain an associative array of OAuth parameters currently set for the AdWordsUser, then places them into a file on separate lines. In addition to the access and refresh tokens, the client id and secret are persisted—for ease of use later—along with two other parameters (timestamp and expires_in), which will be discussed in the section about refreshing access tokens.

If you call this function at the end of your callback script, then the GetOAuth2AccessToken() method should have already set the parameters, so you can simply call it as follows:

<?php
 
require_once 'Google/Api/Ads/AdWords/Lib/AdWordsUser.php';
require_once 'functions.php';
 
$clientId = "YOUR_CLIENT_ID";
$clientSecret = "YOUR_CLIENT_SECRET";
$callbackUrl = "YOUR_REDIRECT_URL";
$tokenFilename = "/tmp/oauth.txt";
 
// Create a new user and set the oAuth settings
$user = new AdWordsUser();
$user->SetOAuth2Info(array(
    "client_id" => $clientId,
    "client_secret" => $clientSecret
));
 
$authCode = $_REQUEST["code"];
$user->GetOAuth2AccessToken($authCode, $callbackUrl);
 
saveAuth($user, $tokenFilename);
?>
Saving OAuth Tokens in a Callback Script

This, of course, is very basic and will only work for one user, so you'll usually want to store the tokens in a database; in a later section I'll discuss how to send an identifier for your user to the OAuth API, and retrieve it from the response so you can store the tokens against the correct user in your database.

Using an Access Token with the API

The tokens saved using the saveAuth() function defined in the last section can be reloaded using the following function:

function loadAuth($filename) {
    $params = explode("\n", file_get_contents($filename));
    return array(
        "client_id" => $params[0],
        "client_secret" => $params[1],
        "access_token" => $params[2],
        "refresh_token" => $params[3],
        "timestamp" => $params[4],
        "expires_in" => $params[5]
    );
}
A Function for Loading OAuth Tokens

This can be used—together with a developer token—to make calls to the AdWords API; here's an example that obtains a list of campaigns within an account:

<?php
 
require_once 'Google/Api/Ads/AdWords/Lib/AdWordsUser.php';
require_once 'functions.php';
 
$tokenFilename = "/tmp/oauth.txt";
$developerToken = "YOUR_DEVELOPER_TOKEN";
 
// Create a new user
$user = new AdWordsUser();
$user->SetDeveloperToken($developerToken);
 
// Load the oAuth settings
$user->SetOAuth2Info(loadAuth($tokenFilename));
 
// Get a list of campaigns
$campaignService = $user->GetService('CampaignService', 'v201209');
$selector = new Selector();
$selector->fields = array('Id', 'Name');
$campaigns = $campaignService->get($selector);
 
print_r($campaigns);
?>
Calling AdWords API Services using OAuth

The details of the API call are beyond the scope of this tutorial, but you might need to set the customer ID for the client account you want to use if your OAuth process authorized an MCC account, which is likely if you're using an AdWords API test account. To set the customer ID, just use the SetClientId() method of the AdWordsUser before making the API call:

$customerId = "123-456-7890";
$user->SetClientId($customerId);

Validating and Refreshing Access Tokens

To refresh an access token, just use the RefreshOAuth2AccessToken() method of the AdWordsUser:

<?php
 
require_once 'Google/Api/Ads/AdWords/Lib/AdWordsUser.php';
require_once 'functions.php';
 
$tokenFilename = "/tmp/oauth.txt";
 
// Create a new user
$user = new AdWordsUser();
 
// Load the oAuth settings
$user->SetOAuth2Info(loadAuth($tokenFilename));
 
// Refresh the token
$user->RefreshOAuth2AccessToken();
// Save the new parameters
saveAuth($user, $tokenFilename);
?>
Refreshing an OAuth Access Token

This script first loads the OAuth settings into a new user, calls the API using RefreshOAuth2AccessToken(), and finally it saves the new access token using the saveAuth() function I defined earlier. It assumes that the user has a valid refresh token, but you might want to use the following code if you don't always request one:

// Check that the token can be refreshed
if ($user->CanRefreshOAuth2AccessToken()) {
    // Refresh the token
    $user->RefreshOAuth2AccessToken();
    // Save the new parameters
    saveAuth($user, $tokenFilename);
} else {
    // Deal with error where the user doesn't have a refresh token 
}
Checking for a Valid Refresh Token

This snippet uses the CanRefreshOAuth2AccessToken() method to check if the AdWordsUser has a refresh token before making the API call. You'll need to modify the code to deal with users who don't have refresh tokens.

To determine if the access token actually needs to be refreshed, you can use the IsOAuth2AccessTokenValid() method. This uses the timestamp and expires_in parameters that are set each time an access token is requested to calculate the time when an access token will become invalid: The timestamp parameter contains the date (as a UNIX timestamp) when the token was requested, and the expires_in parameter indicates the number of seconds after the timestamp that the access token will expire; adding expires_in to timestamp results in a timestamp that can be compared to the current timestamp to check if the token has expired yet. The following snippet adds validity checking logic to the previous example:

// Check that the access token is still valid
if (!$user->IsOAuth2AccessTokenValid()) {
    // Check that the token can be refreshed
    if ($user->CanRefreshOAuth2AccessToken()) {
        // Refresh the token
        $user->RefreshOAuth2AccessToken();
        // Save the new parameters
        saveAuth($user, $tokenFilename);
    } else {
        // Deal with error where the user doesn't have a refresh token 
    }
}
Validating an OAuth Access Token

One exception that this method of access token validation doesn't deal with, however, occurs when an access token has been revoked: In this scenario, the access token becomes invalid regardless of the expiration time, and the token can't be refreshed because the refresh token has also been revoked. This will either cause an AuthenticationError.OAUTH_TOKEN_REVOKED error when you make a call to the AdWords API, or an invalid_grant error when you attempt to use the OAuth API to refresh an access token that you've determined has expired. You need to either handle these errors in your API calls, or just refresh your token every time you use it:

try {
    $user->RefreshOAuth2AccessToken();
    saveAuth($user, $tokenFilename);
} catch (OAuth2Exception $e) {
    print_r($e);
    // Deal with the authorization error
    die;
}
Refreshing an Access Token before Use

This snippet replaces the previous validation procedure, and simply attempts to refresh the access token; if access hasn't been revoked, then you'll get a new one, otherwise you can deal with the exception. Refreshing a token every time you run a script imposes a small performance penalty, but I find it a better approach as the logic is clearer than handling exceptions in two places; however, you shouldn't refresh a token more than once an hour, so you can't use this in all situations.

Revoking Access Tokens

As mentioned in the previous section, users can revoke access to your application from the security settings screen of their Google account (not to be confused with settings available in individual services such as AdWords). If you are logged in to Google, you can find this screen at https://www.google.com/settings/security:

The Google Account Security Screen
The Google Account Security Screen

Clicking on the Manage access button will take you to a page listing the applications authorized to access services within your account:

Authorized Applications
Authorized Applications

This is showing that I've authorized one tool, called Test Product, to access my AdWords data. To revoke access, press the Revoke Access button:

Revoking Access for an Application
Revoking Access for an Application

This method, however, is a bit fiddly for your users, and you should really have your application clean up after itself when a user stops using your tool. The OAuth API has a mechanism for revoking tokens, but it's currently not implemented in the PHP client library; nevertheless, it's not too difficult to implement yourself using cURL:

<?php
 
require_once 'functions.php';
 
$tokenFilename = "/tmp/oauth.txt";
$oauthInfo = loadAuth($tokenFilename);
 
$url = "https://accounts.google.com/o/oauth2/revoke?token={$oauthInfo['access_token']}";
 
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_exec($curl);
curl_close($curl);
?>
Revoking an Access Token

Here cURL is used to make a call to the endpoint at https://accounts.google.com/o/oauth2/revoke; this operation takes a token as a parameter and revokes your access to it. Once you've called this method, then you won't be able to use the access token or request a new one until the user grants you access again.

← Downloading an AdWords API Report Creating Accounts with the AdWords API →

To help me decide what to write about, I'd like to asses the value of my blog posts to see which ones people find most beneficial. If you found the information here useful then could you please +1 it, but if you didn't find what you were looking for then please leave a comment and I'll be happy to help where I can. Thanks!

Comments

I'm keen to get feedback on my posts, so if you have any questions or comments, then please send me a message and I'll be happy to help.

Vipin

Hello Ewan,

Thank you. I am waiting for your reply.

Thanks, Vipin

Reply

Vipin

Hello,

When I try "requesting a token",

My return url like this. http://mywebsite.com/oauth_return.php?oauth_verifier=WZHy5ld3fRel584nGygehrjR&oauth_token=4%2FJoPvimEoz8vXZcjxohw-PjgCQyyQ

I am getting below error.

Fatal error: Uncaught SoapFault exception: [soap:Server] QuotaCheckError.INVALID_TOKEN_HEADER @ ; trigger:[email protected]++INR' in /docroot/Google/Api/Ads/Common/Lib/AdsSoapClient.php:201 Stack trace: #0 /docroot/Google/Api/Ads/Common/Lib/AdsSoapClient.php(201): SoapClient->__soapCall('get', Array, NULL, Array, Array) #1 /docroot/Google/Api/Ads/AdWords/v201109/CampaignService.php(5702): AdsSoapClient->__soapCall('get', Array) #2 /docroot/oauth_return.php(28): CampaignService->get(Object(Selector)) #3 {main} thrown in /docroot/Google/Api/Ads/Common/Lib/AdsSoapClient.php on line 201

Please help.

Thanks, Vipin

Reply

Ewan

Hi Vipin,

Looks like something to do with running the code in the sandbox, I'll try it out and get back to you.

Regards,

Ewan

Reply

Vipin

Any luck on above issue Ewan?

Thanks, Vipin

Reply

Roee Gavriel

Thanks! finely a normal explanation.

Reply

Ewan

Hi Roee,

Glad you found it useful.

I saw some of your questions on Stackoverflow, but haven't had time to answer many lately. The one about adding URLs to user lists sounded interesting; it's possible that's the way it works now since all targeting options have become adgroup level options.

The best place to get answers about the AdWords API is on the official forum. The Google team there is usually pretty good at replying to peoples questions.

Reply