diff --git a/GAFeed.lib.inc b/GAFeed.lib.inc
index 455309f..510a39b 100644
--- a/GAFeed.lib.inc
+++ b/GAFeed.lib.inc
@@ -13,6 +13,10 @@ class GAFeed {
 
   /* Methods require at least v2 */
   const gaFeedVersion = 2;
+  const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke';
+  const OAUTH2_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token';
+  const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth';
+  const SCOPE = 'https://www.googleapis.com/auth/analytics.readonly https://www.google.com/analytics/feeds/';
 
   /* Response object */
   public $response;
@@ -38,117 +42,184 @@ class GAFeed {
   /* Domain of Data Feed API */
   protected $host = 'www.google.com';
 
-  /* Request header source */
-  protected $source = 'drupal';
+  /* OAuth access token */
+  public $access_token;
 
-  /* Default is HMAC-SHA1 */
-  protected $signatureMethod;
+  /* OAuth refresh token */
+  public $refresh_token;
 
-  /* HMAC-SHA1 Consumer data */
-  protected $consumer;
-
-  /* OAuth token */
-  protected $token;
-
-  /* Google authorize callback verifier string */
-  protected $verifier;
+  /* OAuth expiration time */
+  public $expires_at;
 
   /**
    * Constructor for the GAFeed class
    */
-  public function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) {
-    $this->signatureMethod = new OAuthSignatureMethod_HMAC_SHA1();
-    $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret);
-
-    /* Allow developers the option of OAuth authentication without using this class's methods */
-    if (!empty($oauth_token) && !empty($oauth_token_secret)) {
-      $this->token = new OAuthConsumer($oauth_token, $oauth_token_secret);
-    }
+  public function __construct($token = NULL) {
+    $this->access_token = $token;
   }
 
   /**
-   * Set the verifier property
+   * Get the current page url
+   *
+   * @return String
    */
-  public function setVerifier($verifier) {
-    $this->verifier = $verifier;
+  public static function currentUrl() {
+    $https = $_SERVER['HTTPS'] == 'on';
+    $url = $https ? 'https://' : 'http://';
+    $url .= $_SERVER['SERVER_NAME'];
+    if ((!$https && $_SERVER['SERVER_PORT'] != '80') ||
+      ($https && $_SERVER['SERVER_PORT'] != '443')) {
+      $url .= ':' . $_SERVER['SERVER_PORT'];
+    }
+    return $url . str_replace("&code=" . $_GET['code'], '', $_SERVER['REQUEST_URI']);
   }
 
-  /**
-   * Set the host property
-   */
-  public function setHost($host) {
-    $this->host = $host;
+	/**
+	* Create a URL to obtain user authorization.
+	* The authorization endpoint allows the user to first
+	* authenticate, and then grant/deny the access request.
+	* @param string $client_id
+	* @return string
+	*/
+	public function createAuthUrl($client_id) {
+	  	$params = array(
+	      		'response_type=code',
+			    'redirect_uri=' . self::currentUrl(),
+			    'client_id=' . urlencode($client_id),
+			    'scope=' . self::SCOPE,
+			    'access_type=offline',
+			    'approval_prompt=force' 
+	  			);
+
+		$params = implode('&', $params);
+		return self::OAUTH2_AUTH_URL . "?$params";
+	}
+	
+	/**
+	* Authenticate with the Google API
+	*
+	* @param String $client_id
+	* @param String $client_secret
+	* @param String $refresh_token
+	* @return GAFeed
+	*/
+	protected function fetchToken($client_id, $client_secret, $refresh_token=NULL) {
+		$redirect_uri = self::currentUrl();
+		
+		if ($refresh_token) {
+			$params = array(
+					'client_id=' . $client_id,
+					'client_secret=' . $client_secret,
+					'refresh_token=' . $refresh_token,
+					'grant_type=refresh_token',
+					);
+		}
+		else {
+			$params = array(
+					'code=' . $_GET['code'],
+		        	'grant_type=authorization_code',
+		        	'redirect_uri=' . $redirect_uri,
+		        	'client_id=' . $client_id,
+		        	'client_secret=' . $client_secret,
+					);
+		}
+		
+		$data = implode('&', $params);
+		$this->response = drupal_http_request(self::OAUTH2_TOKEN_URI, array('Content-Type' => 'application/x-www-form-urlencoded'), 'POST', $data);
+
+		if (substr($this->response->code, 0, 1) == '2') {
+			$decoded_response = json_decode($this->response->data, true);
+			$this->access_token = $decoded_response['access_token'];
+			$this->expires_at = time() + $decoded_response['expires_in'];
+			if (!$refresh_token) {
+				$this->refresh_token = $decoded_response['refresh_token'];
+			}
+		} 
+		else {
+	        $error_msg = 'Code: !code - Error: !message - Message: !details';
+		    $error_vars = array('!code' => $this->response->code, '!message' => $this->response->error, '!details' => strip_tags($this->response->data));
+		    $this->error =  t($error_msg, $error_vars);
+		    watchdog('google analytics reports', $error_msg, $error_vars, WATCHDOG_ERROR);
+		}
+	}
+	
+	/**
+  * Complete the authentication process.
+  * We got here after being redirected from a successful authorization grant.
+  * Fetch the access token
+  *
+  * @param String $client_id
+  * @param String $client_secret
+  */
+  public function finishAuthentication($client_id, $client_secret) {
+    $this -> fetchToken($client_id, $client_secret);
   }
-
+	
   /**
-   * Set the queryPath property
-   */
-  protected function setQueryPath($path) {
-    $this->queryPath = 'https://'. $this->host .'/'. $path;
+  * Begin authentication by allowing the user to grant/deny access to the Google account
+  *
+  * @param String $client_id
+  */
+  public function beginAuthentication($client_id) {
+	drupal_goto($this -> createAuthUrl($client_id));
   }
 
-  /**
-   * OAuth step #1: Fetch request token.
-   */
-  public function getRequestToken() {
-    $this->setQueryPath('accounts/OAuthGetRequestToken');
-
-    /* xoauth_displayname is displayed on the Google Authentication page */
-    $params = array(
-      'scope' => 'https://www.google.com/analytics/feeds',
-      'oauth_callback' => url('google-analytics-reports/oauth', array('absolute' => TRUE)),
-      'xoauth_displayname' => t('Google Analytics Reports Drupal module'),
-    );
+	/**
+	* Fetches a fresh access token with the given refresh token.
+	* @param String $client_id
+	* @param String $client_secret
+	* @param string $refresh_token
+	*/
+	public function refreshToken($client_id, $client_secret, $refresh_token) {
+		$this->refresh_token = $refresh_token;
+		$this -> fetchToken($client_id, $client_secret, $refresh_token);
+	}
+	
+	/**
+	* Revoke an OAuth2 access token or refresh token. This method will revoke the current access
+	* token, if a token isn't provided.
+	* @param string|NULL $token The token (access token or a refresh token) that should be revoked.
+	* @return boolean Returns True if the revocation was successful, otherwise False.
+	*/
+	public function revokeToken($token = NULL) {
+		if (!$token) {
+			$token = $this->refresh_token;
+		}
+		
+		$this->response = drupal_http_request(self::OAUTH2_REVOKE_URI, array('Content-Type' => 'application/x-www-form-urlencoded'), 'POST', "token=$token");
+
+		if ($this->response->code == 200) {
+			$this->access_token = NULL;
+			return true;
+		}
+
+		return false;
+	}
+	
+	/**
+  * Generate authorization token header for all requests
+  *
+  * @return Array
+  */
+	public function generateAuthHeader($token=NULL) {
+		if ($token == NULL) {
+			$token = $this->access_token;
+		}
+		return array('Authorization' => 'Bearer ' . $token);
+	}
 
-    $this->query($this->queryPath, $params, 'GET', array('refresh' => TRUE));
-    parse_str($this->response->data, $token);
-    $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
-    return $token;
-  }
 
   /**
-   * OAuth step #2: Authorize request token.
-   */
-  public function obtainAuthorization($token) {
-    $this->setQueryPath('accounts/OAuthAuthorizeToken');
-
-    /* hd is the best way of dealing with users with multiple domains verified with Google */
-    $params = array(
-      'oauth_token' => $token['oauth_token'],
-      'hd' => variable_get('google_analytics_reports_hd', 'default'),
-    );
-
-    drupal_goto($this->queryPath, $params);
-  }
-
-  /**
-   * OAuth step #3: Fetch access token.
-   */
-  public function getAccessToken() {
-    $this->setQueryPath('accounts/OAuthGetAccessToken');
-
-    $params = array(
-      'oauth_verifier' => $this->verifier,
-    );
-
-    $this->query($this->queryPath, $params, 'GET', array('refresh' => TRUE));
-    parse_str($this->response->data, $token);
-    $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
-    return $token;
-  }
-
-  /**
-   * Revoke OAuth token.
-   */
-  public function revokeToken() {
-    $this->setQueryPath('accounts/AuthSubRevokeToken');
-    $this->query($this->queryPath, array(), 'GET', array('refresh' => TRUE));
+   * Set the queryPath property for all Data Export API requests
+  */
+  protected function setQueryPath($path) {
+    $this->queryPath = 'https://'. $this->host .'/'. $path;
   }
 
   /**
    * Public query method for all Data Export API features.
    */
-  public function query($path, $params = array(), $method = 'GET', $cache_options = array()) {
+  public function query($url, $params = array(), $method = 'GET', $headers, $cache_options) {
 
     $params_defaults = array(
       'v' => self::gaFeedVersion,
@@ -175,21 +246,12 @@ class GAFeed {
       $this->fromCache = TRUE;
     }
     else {
-      $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $this->queryPath, $params);
-      $request->sign_request($this->signatureMethod, $this->consumer, $this->token);
-      switch ($method) {
-        case 'GET':
-          $this->request($request->to_url());
-          break;
-        case 'POST':
-          $this->request($request->get_normalized_http_url(), $request->get_parameters(), 'POST');
-          break;
-      }
+      $this->request($url, $params, $headers);
+    }
 
-      /* Do not cache erroneous queries */
-      if (empty($this->error)) {
-        cache_set($cache_options['cid'], $this->response, 'cache', $cache_options['expire']);
-      }
+    /* Do not cache erroneous queries */
+    if (empty($this->error)) {
+      cache_set($cache_options['cid'], $this->response, 'cache', $cache_options['expire']);
     }
 
     return (empty($this->error));
@@ -198,7 +260,7 @@ class GAFeed {
   /**
    * Execute a query
    */
-  protected function request($url, $params = array(), $method = 'GET') {
+  protected function request($url, $params = array(), $headers, $method = 'GET') {
     $data = '';
     if (count($params) > 0) {
       if ($method == 'GET') {
@@ -209,7 +271,6 @@ class GAFeed {
       }
     }
 
-    $headers = array();
     $this->response = drupal_http_request($url, $headers, $method, $data);
     if ($this->response->code != '200') {
       // data is undefined if the connection failed.
@@ -234,7 +295,7 @@ class GAFeed {
     );
 
     $this->setQueryPath('analytics/feeds/accounts/default');
-    if ($this->query($this->queryPath, $params, 'GET', $cache_options)) {
+    if ($this->query($this->queryPath, $params, 'GET', $this->generateAuthHeader(), $cache_options)) {
       $this->sanitizeAccount();
     }
   }
@@ -347,7 +408,7 @@ class GAFeed {
     $parameters['max-results'] = $params['max_results'];
 
     $this->setQueryPath('analytics/feeds/data');
-    if ($this->query($this->queryPath, $parameters, 'GET', $cache_options)) {
+    if ($this->query($this->queryPath, $parameters, 'GET', $this->generateAuthHeader(), $cache_options)) {
       $this->sanitizeReport();
     }
   }
diff --git a/google_analytics_api.info b/google_analytics_api.info
index e211d8a..048abb5 100644
--- a/google_analytics_api.info
+++ b/google_analytics_api.info
@@ -2,4 +2,9 @@ name = "Google Analytics API"
 package = Statistics
 description = "API to access statistics from the Google Analytics Data Export API."
 core = 6.x
-dependencies[] = oauth_common
\ No newline at end of file
+; Information added by drupal.org packaging script on 2012-04-16
+version = "6.x-1.1"
+core = "6.x"
+project = "google_analytics_reports"
+datestamp = "1341941974"
+
diff --git a/google_analytics_api.module b/google_analytics_api.module
index 0ab7f1a..8128f43 100644
--- a/google_analytics_api.module
+++ b/google_analytics_api.module
@@ -74,15 +74,58 @@ function google_analytics_api_theme() {
 
 
 /**
- * Instantiate a new GAFeed object.
- */
+ * Instantiate a new authenticated GAFeed object or NULL if no authentication has taken place.
+*/
 function google_analytics_api_new_gafeed() {
-  module_load_include('inc', 'google_analytics_api', 'GAFeed.lib');
-  $key = variable_get('google_analytics_reports_consumer_key', 'anonymous');
-  $secret = variable_get('google_analytics_reports_consumer_secret', 'anonymous');
-  $oauth_token = variable_get('google_analytics_reports_oauth_token', NULL);
-  $oauth_token_secret = variable_get('google_analytics_reports_oauth_token_secret', NULL);
-  return new GAFeed($key, $secret, $oauth_token, $oauth_token_secret);
+	module_load_include('inc', 'google_analytics_api', 'GAFeed.lib');
+	if (variable_get('google_analytics_reports_access_token', NULL) && time() < variable_get('google_analytics_reports_expires_at', NULL)) {
+		// If the access token is still valid, return an authenticated GAFeed
+		return new GAFeed(variable_get('google_analytics_reports_access_token', NULL));
+	}
+	else if (variable_get('google_analytics_reports_refresh_token', NULL)) {
+		// If the site has an access token and refresh token, but the access
+		// token has expired, authenticate the user with the refresh token 
+		$client_id = variable_get('google_analytics_reports_client_id', NULL);
+		$client_secret = variable_get('google_analytics_reports_client_secret', NULL);
+		$refresh_token = variable_get('google_analytics_reports_refresh_token', NULL);
+
+		try {
+			$GAFeed = new GAFeed();
+			$GAFeed -> refreshToken($client_id, $client_secret, $refresh_token);
+			
+			variable_set("google_analytics_reports_access_token", $GAFeed->access_token);
+			variable_set("google_analytics_reports_expires_at", $GAFeed->expires_at);
+			return $GAFeed;
+		}
+		catch (Exception $e) {
+			drupal_set_message(t("There was an authentication error. Message: " . $e->getMessage()), 'error', false);
+			return NULL;
+		}
+	}
+	else if (isset($_GET['code'])) {
+		// If there is no access token or refresh token and client is returned
+		// to the config page with an access code, complete the authentication
+		$client_id = variable_get('google_analytics_reports_client_id', NULL);
+		$client_secret = variable_get('google_analytics_reports_client_secret', NULL);
+		
+		try {
+			$GAFeed = new GAFeed();
+			$GAFeed -> finishAuthentication($client_id, $client_secret);
+		
+			variable_set('google_analytics_reports_access_token', $GAFeed->access_token);
+			variable_set('google_analytics_reports_expires_at', $GAFeed->expires_at);
+			variable_set('google_analytics_reports_refresh_token', $GAFeed->refresh_token);
+			
+			drupal_goto(GAFeed::currentUrl());
+		}
+		catch (Exception $e) {
+			drupal_set_message(t("There was an authentication error. Message: " . $e->getMessage()), 'error', false);
+			return NULL;
+		}
+	}
+	else {
+		return NULL;
+	}
 }
 
 /**
@@ -143,14 +186,14 @@ function google_analytics_api_report_data($params = array(), $cache_options = ar
  * Programatically revoke token.
  */
 function google_analytics_api_revoke() {
-  $GAFeed = google_analytics_api_new_gafeed();
-  $GAFeed->revokeToken();
-  variable_del('google_analytics_reports_profile_id');
-  variable_del('google_analytics_reports_consumer_key');
-  variable_del('google_analytics_reports_consumer_secret');
-  variable_del('google_analytics_reports_oauth_token');
-  variable_del('google_analytics_reports_oauth_token_secret');
-  variable_del('google_analytics_reports_cache_length');
+	google_analytics_api_new_gafeed()->revokeToken();
+	variable_del("google_analytics_reports_client_id");
+	variable_del("google_analytics_reports_client_secret");
+	variable_del("google_analytics_reports_access_token");
+	variable_del("google_analytics_reports_expires_at");
+	variable_del("google_analytics_reports_refresh_token");
+	variable_del("google_analytics_reports_profile_id");
+	variable_del('google_analytics_reports_cache_length');
 }
 
 /**
diff --git a/google_analytics_api.pages.inc b/google_analytics_api.pages.inc
index 7284141..57f09e8 100644
--- a/google_analytics_api.pages.inc
+++ b/google_analytics_api.pages.inc
@@ -10,8 +10,15 @@
  */
 function google_analytics_api_admin() {
 
-  $form = array();
-  $account = google_analytics_api_account_data();
+	$form = array();
+	$GAFeed = google_analytics_api_new_gafeed();
+
+	if ($GAFeed) {
+		$account = google_analytics_api_account_data();
+	}
+	else {
+		$account = NULL;
+	}
 
   /* If there is at least one profile */
   if (!empty($account->results)) {
@@ -95,12 +102,23 @@ function google_analytics_api_admin() {
       '#collapsible' => TRUE,
       '#collapsed' => FALSE,
     );
-    $form['setup']['google_analytics_reports_hd'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Google Apps for Business Domain (optional)'),
-      '#description' => t('Provide the domain name (example.com) if your domain is registered with Google Apps for Business.  Otherwise, leave blank.'),
-      '#default_value' => variable_get('google_analytics_reports_hd', ''),
-    );
+    $form['setup']['client_id'] = array(
+		'#type' => 'textfield',
+		'#title' => t('Client ID'),
+		'#default_value' => variable_get('google_analytics_reports_client_id', ''),
+		'#size' => 30,
+		'#description' => t('Client ID created for the app in the access tab of the ') . l('Google API Console', 'http://code.google.com/apis/console', array('attributes' => array('target' => '_blank'))),
+		'#weight' => -9,
+	);
+
+	$form['setup']['client_secret'] = array(
+		'#type' => 'textfield',
+		'#title' => t('Client Secret'),
+		'#default_value' => variable_get('google_analytics_reports_client_secret', ''),
+		'#size' => 30,
+		'#description' => t('Client Secret created for the app in the Google API Console'),
+		'#weight' => -8,
+	);
    $form['setup']['setup_submit'] = array(
       '#type' => 'submit',
       '#value' => t('Start setup and authorize account'),
@@ -110,38 +128,33 @@ function google_analytics_api_admin() {
 }
 
 /**
- * Submit handler.  Steps throuh the OAuth process, revokes tokens, saves profiles.
- */
+ * Submit handler.  Begins the OAuth process, revokes tokens, saves profiles.
+*/
 function google_analytics_api_admin_submit($form, &$form_state) {
-  $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
-  cache_clear_all('GAFeed', 'cache', '*');
-  switch ($op) {
-    case t('Start setup and authorize account'):
-        variable_set('google_analytics_reports_hd', $form_state['values']['google_analytics_reports_hd']);
-        /* Anonymous keys are a Google default */
-        $key = variable_get('google_analytics_reports_consumer_key', 'anonymous');
-        $secret = variable_get('google_analytics_reports_consumer_secret', 'anonymous');
-        module_load_include('inc', 'google_analytics_api', 'GAFeed.lib');
-        $GAFeed = new GAFeed($key, $secret);
-
-        /* Step #1 of OAuth */
-        $token = $GAFeed->getRequestToken();
-        $_SESSION['google_analytics_reports_oauth']['token'] = $token;
-        $_SESSION['google_analytics_reports_oauth']['destination'] = $_GET['q'];
-
-        /* Step #2 of OAuth */
-        $GAFeed->obtainAuthorization($token);
-      break;
-    case t('Save settings'):
-        variable_set('google_analytics_reports_profile_id', $form_state['values']['google_analytics_reports_profile_id']);
-        variable_set('google_analytics_reports_cache_length', $form_state['values']['google_analytics_reports_cache_length']);
-        drupal_set_message(t('Settings have been saved successfully.'));
-      break;
-    case t('Revoke access token'):
-        google_analytics_api_revoke();
-        drupal_set_message(t('Access token has been successfully revoked.'));
-      break;
-  }
+	$op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
+	cache_clear_all('GAFeed', 'cache', '*');
+	switch ($op) {
+	    case t('Start setup and authorize account'):
+			$client_id = $form_state['values']['client_id'];
+			$client_secret = $form_state['values']['client_secret'];
+		
+			variable_set('google_analytics_reports_client_id', $client_id);
+			variable_set('google_analytics_reports_client_secret', $client_secret);
+		
+	        module_load_include('inc', 'google_analytics_api', 'GAFeed.lib');
+	        $GAFeed = new GAFeed();
+			$GAFeed -> beginAuthentication($client_id);
+			break;
+		case t('Save settings'):
+	        variable_set('google_analytics_reports_profile_id', $form_state['values']['google_analytics_reports_profile_id']);
+	        variable_set('google_analytics_reports_cache_length', $form_state['values']['google_analytics_reports_cache_length']);
+	        drupal_set_message(t('Settings have been saved successfully.'));
+	    	break;
+	    case t('Revoke access token'):
+	        google_analytics_api_revoke();
+	        drupal_set_message(t('Access token has been successfully revoked.'));
+	      	break;
+	}
 }
 
 /**
diff --git a/google_analytics_reports/google_analytics_reports.pages.inc b/google_analytics_reports/google_analytics_reports.pages.inc
index 97079b9..dc329e9 100644
--- a/google_analytics_reports/google_analytics_reports.pages.inc
+++ b/google_analytics_reports/google_analytics_reports.pages.inc
@@ -10,7 +10,7 @@
  * @return An HTML summary of the site-wide statistics.
  */
 function google_analytics_reports_summary_page() {
-  if (!variable_get('google_analytics_reports_oauth_token', FALSE)) {
+  if (!variable_get('google_analytics_reports_access_token', FALSE)) {
     drupal_set_message(t('You must <a href="!url">authorize</a> Drupal to use your Analytics account before you can view reports.', array('!url' => url('admin/settings/google-analytics-reports'))), 'warning');
     return ' ';
   }
