This document outlines how to use
OAuth 2.0 validation to access Google API feed endpoints. The Webmaster Tools API is used here only as an example of how to interact with a Google API feed. The example code in this document is written in PHP.
OAuth 2.0
Google is now supporting OAuth 2.0 for API security validation. To summarize the
draft specification of the OAuth 2.0 protocol, OAuth enables clients to access protected resources by obtaining an access token as "a string representing an access authorization issued to the client" rather than using the resource owner's credentials. Tokens are issued to clients by an authorization server with the approval of the resource owner. For more information on OAuth 2.0, please reference the Google documentation
Using OAuth 2.0 to Access Google APIs.
Getting a Google API Key
Before you begin, you must
register your application with Google and get an API key. This registration associates your Google account with your application. I won’t go into great detail here, but in short here are the steps to get a Google API key for your application:
- If you don’t already have an API project, create one. (https://code.google.com/apis/console)
- Under the Project menu (top left) select API Access
- Click on Create an OAuth 2.0 client ID…
- You will be prompted to fill in your branding information. The name of your application (Product name) and the Product Logo will be displayed to the user during the authentication process.
- When you click next, you will be prompted to fill in the Client ID settings. Under Application type, be sure Web application is selected. Next to Your site or hostname click on (more options). The dialog box will look like this:
- Authorized Redirect URIs: During the authentication process, the OAuth2 server will prompt the user to Allow or disallow your application to have access to the Google account. You must register at least one URL here to which you want the OAuth2 server to send the permission response. You can register multiple redirect URLs in this box.
- Enter your root domain in the Authorized Javascript Origins – this field is not used in this example.
- Click on the Create client ID button. You will then be taken to your API Access page. You will see four fields in the Client ID for web applications box:
Client ID: xxxxxxxx.apps.googleusercontent.com
Client secret: xcfrtgd_dfLcHxx6
Redirect URIs: https://www.example.com/oauth2callback
JavaScript origins: https://www.example.com
Ask permission to access the Google Account
The first step in OAuth2.0 Server side authentication is for the application to send a request to the Google OAuth2 server with the Client ID information and the redirect URL. The OAuth2 server prompts the user to allow or disallow your application to access the Google account.
If the user clicks on the
No thanks button, the redirect URL is called with the URI parameter:
?error=access_denied
If the user clicks on the
Allow Access button, the redirect URL is called with the URI parameter:
?
code=4/FXxxxxxxxxxxxxx_LcSwvVZGk .
The value of the
code parameter is the authorization code. This authorization code needs to be swapped for an access token, but first, here is the code to get the authorization code.
1 <?php
2 $OAuth = array(
3 'oauth_uri' => 'https://accounts.google.com/o/oauth2/auth',
4 'client_id' => 'insert your Client ID here',
5 'redirect_uri' => 'http://example.com/OAuth2' // replace with your redirect uri
6 );
7 $title = 'No Code';
8 $AuthCode = 'Null';
9
10
11 $error = _get_url_param($_SERVER['REQUEST_URI'], 'error');
12 if ($error != NULL)
13 {
14 $title = $error;
15 }
16 else
17 {
18 $AuthCode = _get_url_param($_SERVER['REQUEST_URI'], 'code');
19 if ($AuthCode == NULL)
20 {
21 $OAuth_request = _formatOAuthReq($OAuth,
22 "https://www.google.com/webmasters/tools/feeds/sites/");
23
24 header('Location: ' . $OAuth_request);
25 exit;
26 }
27 else
28 {
29 $title = 'Got Authorization Code';
30 }
31 }
32
33 function _formatOAuthReq($OAuthParams, $scope)
34 {
35 $uri = $OAuthParams['oauth_uri'];
36 $uri .= "?client_id=" . $OAuthParams['client_id'];
37 $uri .= "&redirect_uri=" . $OAuthParams['redirect_uri'];
38 $uri .= "&scope=" . $scope;
39 $uri .= "&response_type=code";
40
41 return $uri;
42 }
43
44 function _get_url_param($url, $name)
45 {
46 parse_str(parse_url($url, PHP_URL_QUERY), $params);
47 return isset($params[$name]) ? $params[$name] : null;
48 }
49 ?>
50 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
51 <html>
52 <head>
53 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
54 <title><?= $title; ?></title>
55 </head>
56 <body>
57 <h1>OAuth2 Authorization Code</h1>
58 <p>Code = <?= $AuthCode; ?></p>
59
60 </body>
61 </html>
62
On line 22 in the source code listing above is the URL of the Google Webmaster Tools '
sites' feed. This feed is referred to as the 'scope' of the authorization meaning that the authorization code is only valid for this feed. Each feed requires its own authorization code. You can consult the
Google Webmaster Tools API documentation if you require more information on this feed.
Requesting the Access Token
Now that we have the authorization code we need to exchange it for an access token and refresh token. This requires POSTing parameters to the OAuth 2.0 server. To do the POST, I am using the PHP curl library. Changes from the first listing include: the $OAuth array defined on line 2 of the source listing was modified, the $token array was added, and there were two additional functions added to format and POST the request. Here is the PHP code:
1 <?php
2 $OAuth = array(
3 'oauth_uri' => 'https://accounts.google.com/o/oauth2/auth',
4 'client_id' => 'insert your Client ID here',
5 'client_secret' => 'insert your client secret here',
6 'redirect_uri' => 'http://example.com/OAuth2', // replace with your redirect uri
7 'oauth_token_uri' => 'https://accounts.google.com/o/oauth2/token'
8
9 );
10 $token = array(
11 'access_token' => '',
12 'token_type' => '',
13 'expires_in' => '',
14 'refresh_token' => ''
15 );
16
17 $title = 'No Code';
18 $AuthCode = 'Null';
19
20
21 $error = _get_url_param($_SERVER['REQUEST_URI'], 'error');
22 if ($error != NULL)
23 {
24 $title = $error;
25 }
26 else
27 {
28 $AuthCode = _get_url_param($_SERVER['REQUEST_URI'], 'code');
29 if ($AuthCode == NULL)
30 {
31 $OAuth_request = _formatOAuthReq($OAuth,
32 "https://www.google.com/webmasters/tools/feeds/sites/");
33
34 header('Location: ' . $OAuth_request);
35 exit;
36 }
37 else
38 {
39 $title = 'Got Authorization Code';
40
41 $token_response = _get_auth_token($OAuth, $AuthCode);
42 $json_obj = json_decode($token_response);
43 $token['access_token'] = $json_obj->access_token;
44 $token['token_type'] = $json_obj->token_type;
45 $token['expires_in'] = $json_obj->expires_in;
46 $token['refresh_token'] = $json_obj->refresh_token;
47 echo 'access_token = ' . $json_obj->access_token;
48 }
49 }
50
51 function _get_auth_token($params, $code)
52 {
53 $url = $params['oauth_token_uri'];
54
55 $fields = array(
56 'code' => $code,
57 'client_id' => $params['client_id'],
58 'client_secret' => $params['client_secret'],
59 'redirect_uri' => $params['redirect_uri'],
60 'grant_type' => 'authorization_code'
61 );
62 $response = _do_post($url, $fields);
63 return $response;
64 }
65
66 function _do_post($url, $fields)
67 {
68 $fields_string = '';
69
70 foreach ($fields as $key => $value)
71 {
72 $fields_string .= $key . '=' . $value . '&';
73 }
74 $fields_string = rtrim($fields_string, '&');
75
76 $ch = curl_init();
77 curl_setopt($ch, CURLOPT_URL, $url);
78 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
79 curl_setopt($ch, CURLOPT_POST, count($fields));
80 curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
81 $response = curl_exec($ch);
82 curl_close($ch);
83
84 return $response;
85 }
The response from the POST is a JSON array which is decoded on line 42 and stored in the $token array. The access token has a life of 1 hour.
Using the access token to request data from the Google Webmaster Tools 'sites' feed
Now your server app is fully authorized and we are ready to request data from a feed. Since the scope of the authorization is for the Webmaster Tools sites feed, we can only request services from that feed. The following code retrieves the list of servers registered in your Google Webmaster Account. The request is sent to the sites feed and the response is in xml format. The _parse_wmt_sites_response function parses the title field for each entry and builds an HTML list of the servers. The title field contains the URL of the site.
36 else
37 {
38 $title = 'Got Authorization Code';
39
40 $token_response = _get_auth_token($OAuth, $AuthCode);
41 $json_obj = json_decode($token_response);
42 $token['access_token'] = $json_obj->access_token;
43 $token['token_type'] = $json_obj->token_type;
44 $token['expires_in'] = $json_obj->expires_in;
45 $token['refresh_token'] = $json_obj->refresh_token;
46
47 $sites = _get_wmt_sites_feed($token);
48 }
49 }
50
51
52 function _get_wmt_sites_feed($access_tokens)
53 {
54 $post_string = "https://www.google.com/webmasters/tools/feeds/sites/";
55 $post_string .= '?v=2';
56 $post_string .= '&oauth_token=' . $access_tokens['access_token'];
57
58 $response = file_get_contents($post_string);
59 return _parse_wmt_sites_response($response);
60 }
61
62 function _parse_wmt_sites_response($response)
63 {
64 $xml = simplexml_load_string($response);
65 $response = '<br />';
66 foreach ($xml->entry as $entry)
67 {
68 foreach ($entry->title as $title)
69 {
70 $response .= "<p><a href=\"$title\" target=\"_blank\">$title</a></p>";
71 }
72 }
73 return $response;
74 }
Access token expiration
When the access token expires an API call will return a HTTP 401 Unauthorized. To get a refresh token you can POST at any time to the token endpoint with the refresh token and the 'grant_type' parameter set to 'refresh_token'.
90 function _get_refresh_token($params, $code)
91 {
92 $url = $params['oauth_token_uri'];
93
94 $fields = array(
95 'code' => $code,
96 'client_id' => $params['client_id'],
97 'client_secret' => $params['client_secret'],
98 'refresh_token' => $token['refresh_token'],
99 'grant_type' => 'refresh_token'
100 );
101 $response = _do_post($url, $fields);
102 return $response;
103 }