2
votes

I have attempted many solutions provided on Stack Exchange to obtain a refresh token, and they all fail. Below is my whole controller. As you can see, I have included $client->setAccessType('offline') and $client->setApprovalPrompt('force').

In addition, I have ran the revoke token many times, and I have gone into my Google Account here (https://myaccount.google.com/permissions), and removed access. None of these attempts provided me with a refresh token when I made a new authorization.

<?php
/**
 * @file
 * Contains \Drupal\hello\GAOauthController.
 */

namespace Drupal\ga_reports_per_user\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Google_Client;
use Google_Service_Analytics;
use Drupal\group\Context\GroupRouteContextTrait;

class GAOauthController extends ControllerBase {

  use GroupRouteContextTrait;

  public function authorize($group = NULL) {
    $client = new Google_Client();
    $credentials_file = \Drupal::service('file_system')->realpath("private://") . '/client_credentials.json';
    $client->setAuthConfig($credentials_file);
    $client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);

    if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
      $protocol = "https";
    }
    else {
      $protocol = "http";
    }
    $redirect_uri = $protocol . '://' . $_SERVER['HTTP_HOST'] . '/finish_google_oauth';
    $client->setState($group);
    $client->setRedirectUri($redirect_uri);
    $client->setAccessType('offline');
    $client->setApprovalPrompt('force');
    $auth_url = $client->createAuthUrl();
    return new TrustedRedirectResponse($auth_url);
  }

  public function finishOauth() {
    if (isset($_GET['code'])) {
      $client = new Google_Client();
      $credentials_file = \Drupal::service('file_system')->realpath("private://") . '/client_credentials.json';
      $client->setAuthConfig($credentials_file);
      $client->addScope(Google_Service_Analytics::ANALYTICS_READONLY);
      if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
        $protocol = "https";
      }
      else {
        $protocol = "http";
      }
      $redirect_uri = $protocol . '://' . $_SERVER['HTTP_HOST'] . '/finish_google_oauth';
      $client->setRedirectUri($redirect_uri);
      $client->setAccessType('offline');
      $client->setApprovalPrompt('force');
      $client->authenticate($_GET['code']);
      $token = $client->getAccessToken();
      $refreshToken = $client->getRefreshToken();
      $client->setAccessToken($token);

      $group_entity = \Drupal::entityTypeManager()->getStorage('group')->load($_GET['state']);

      $group_entity->field_google_oauth_token->value = $token['access_token'];
      $group_entity->field_google_oauth_token_type->value = $token['token_type'];
      $group_entity->field_google_oauth_token_created->value = $token['created'];
      $group_entity->field_google_oauth_token_expire->value = $token['expires_in'];

      $save_status = $group_entity->save();

      return new RedirectResponse('/group/' . $_GET['state']);
    }
  }

  public function revoke($group = NULL){
    $client = new Google_Client();
    $group_entity = \Drupal::entityTypeManager()->getStorage('group')->load($group);
    $result = $client->revokeToken($group_entity->field_google_oauth_token->value);

    $group_entity->field_google_oauth_token->value = '';
    $group_entity->field_google_oauth_token_type->value = '';
    $group_entity->field_google_oauth_token_created->value = '';
    $group_entity->field_google_oauth_token_expire->value = '';

    $group_entity->save();

    return new RedirectResponse('/group/' . $group);

  }
}
1

1 Answers

1
votes

If you have already requested an access token for that login / dev. token combo, it won't return it again for you. You'll have to revoke access by going to https://myaccount.google.com/permissions. Find your app, revoke access, and try again.

Source: I had this exact same problem and after nearly pulling my hair out, I figured this out.