5

Poiché l'autenticazione di accesso di Google è disabilitata dalla scorsa settimana, sto cercando di ottenere oAuth 2.0 che funzioni con un account di servizio. Vogliamo offrire agli utenti della nostra applicazione Web interna l'opportunità di impostare Out of Office.SDK amministratore Google: non sei autorizzato ad accedere a questa API

Ho scaricato l'ultimo Google APIs Client Library for PHP. Nel Google Developer Console, ho creato un nuovo progetto per la mia applicazione e creato una credenziale Service account. Ho anche attivato il servizio API: Admin SDK nella Console per gli sviluppatori.

enter image description here

mi hanno concesso l'accesso ID account utente agli scopi corretti (credo): enter image description here

Quando uso l'esempio di servizio-account.php e modificare i dettagli, ricevo un JSON con un token di accesso, ma quando faccio una richiesta CURL (come prima) per ottenere le impostazioni e-mail da un utente, si verifica l'errore "You are not authorized to access this API.".

Il mio codice:

<?php 

include_once "templates/base.php"; 
require_once realpath(dirname(__FILE__) . '/../src/Google/autoload.php'); 
$client_id = '124331845-DELETEDPART-hbh89pbgl20citf6ko.apps.googleusercontent.com'; //Client ID 
$service_account_name = '[email protected]com'; //Email Address 
$key_file_location = 'globaltext-4ce09b20cb73.p12'; //key.p12 

$client = new Google_Client(); 
if (isset($_SESSION['service_token'])) { 
    $client->setAccessToken($_SESSION['service_token']); 
} 
$key = file_get_contents($key_file_location); 
$cred = new Google_Auth_AssertionCredentials(
    $service_account_name, 
    array('https://apps-apis.google.com/a/feeds/emailsettings/2.0/'), 
    $key 
); 
$client->setAssertionCredentials($cred); 
if ($client->getAuth()->isAccessTokenExpired()) { 
    $client->getAuth()->refreshTokenWithAssertion($cred); 
} 

$aOutput = json_decode($client->getAccessToken()); 

$strEmailAdresSplit = explode('@', "[email protected]"); 
$strDomein = $strEmailAdresSplit[1]; 
$strAlias = $strEmailAdresSplit[0]; 

$resConnectionJobs = curl_init(); 
$aHeader = array(); 
$aHeader[] = 'Authorization: Bearer '.$aOutput->access_token; 
$aHeader[] = 'Content-Type: application/atom+xml'; 

curl_setopt($resConnectionJobs, CURLOPT_URL, "https://apps-apis.google.com/a/feeds/emailsettings/2.0/DOMAIN.EXTENSION/FIRSTNAME.LASTNAME/vacation"); 
curl_setopt($resConnectionJobs, CURLOPT_SSL_VERIFYPEER, FALSE); 
curl_setopt($resConnectionJobs, CURLOPT_HTTPHEADER, $aHeader); 
curl_setopt($resConnectionJobs, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($resConnectionJobs, CURLOPT_HEADER, false); 

$oCurlData = curl_exec($resConnectionJobs); 

curl_close($resConnectionJobs); 
echo $oCurlData; 

?> 
+0

quello che l'accesso ti è concedere l'account di servizio? amministratore super o amministratore delegato? – DaImTo

+0

Dove posso trovare questo? Sono in grado di accedere alla console degli sviluppatori, ma non riesco a trovare i ruoli utente. – global

+0

@DalmTo Ora ho cambiato la lingua in inglese e posso confermare che l'utente è Super Admin. – global

risposta

1

Sei sicuro le credenziali sono OK?

Si prega di provare la seguente procedura per assicurarsi di avere le giuste credenziali.

Creare le chiavi API

Vai alla developer's console e procedere come segue:

  • Seleziona il tuo progetto
  • Scegliere la voce di menu "API & auth"
  • Scegliere la voce di menu " App registrata "
  • Registrare un'applicazione di tipo" applicazione web "
  • Scegli una delle seguenti opzioni, a seconda del tipo di app che stai creando. linguaggi lato server dovrebbe utilizzare questa opzione:
    • chiave per le applicazioni del server (con bloccaggio IP)

Ottenere token di accesso & token di aggiornamento

Creare un file contiene il seguente codice:

<?php 

if (isset($_GET['code'])) { 
    // try to get an access token 
    $code = $_GET['code']; 
    $url = 'https://accounts.google.com/o/oauth2/token'; 
    $params = array(
     "code" => $code, 
     "client_id" => YOUR_CLIENT_ID, 
     "client_secret" => YOUR_CLIENT_SECRET, 
     "redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"], 
     "grant_type" => "authorization_code" 
    ); 

    $ch = curl_init(); 
    curl_setopt($ch, constant("CURLOPT_" . 'URL'), $url); 
    curl_setopt($ch, constant("CURLOPT_" . 'POST'), true); 
    curl_setopt($ch, constant("CURLOPT_" . 'POSTFIELDS'), $params); 
    $output = curl_exec($ch); 
    $info = curl_getinfo($ch); 
    curl_close($ch); 
    if ($info['http_code'] === 200) { 
     header('Content-Type: ' . $info['content_type']); 
     return $output; 
    } else { 
     return 'An error happened'; 
    } 
} else { 

    $url = "https://accounts.google.com/o/oauth2/auth"; 

    $params = array(
     "response_type" => "code", 
     "client_id" => YOUR_CLIENT_ID, 
     "redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"], 
     "scope" => "https://www.googleapis.com/auth/plus.me" 
    ); 

    $request_to = $url . '?' . http_build_query($params); 

    header("Location: " . $request_to); 
} 

Ora, sostituire YOUR_CLIENT_ID e YOUR_CLIENT_SECRET con l'ID client e il segreto del client.

Assicurarsi che l'ambito sia corretto. Ad esempio, dovrebbe essere https://www.googleapis.com/auth/analytics se si desidera ottenere l'accesso ad Analytics.

Se si esegue il file, è necessario ottenere una schermata di approvazione OAuth2.

Se ora si preme Accept, si dovrebbe ottenere un risultato simile al seguente:

{ 
    "access_token" : YOUR_ACCESS_TOKEN, 
    "token_type" : "Bearer", 
    "expires_in" : 3600, 
    "refresh_token" : YOUR_REFRESH_TOKEN 
} 

Il risultato può contenere campi aggiuntivi, a seconda di quale portata si sta applicando per.


Collegamento con i sistemi di Google in background

Una volta che il sopra per lavorare, l'applicazione deve implementare il seguente flusso di lavoro:

1) Verificare se l'input contiene un parametro GET chiamato "codice". Se è presente "codice", ottieni un nuovo token di accesso e ripeti questo passaggio (aggiorna la pagina) Se "codice" non è presente, vai al passaggio 2.

2) Controlla se hai le credenziali memorizzate per il tuo servizio . Se sono presenti credenziali, controlla se il tuo token di accesso è scaduto o scadrà presto. Quindi andare al passaggio 3. Se le credenziali non sono presenti, andare al percorso auth del servizio per ottenere il codice di autenticazione e tornare al passaggio 1 (assicurarsi che Google reindirizzi al proprio URL corrente).

3) Se è necessario eseguire l'aggiornamento, aggiornare la pagina e tornare al passaggio 1. Se l'aggiornamento non è necessario, si è pronti a fare effettivamente ciò che si voleva fare in primo luogo.


La libreria PHP di Google si prende cura del flusso di oAuth2 per te. Se stai utilizzando la loro libreria, ognuno dei passaggi del processo in 3 passaggi è gestito dalla biblioteca e dovresti essere in grado di fare subito tutto ciò che vuoi fare con i servizi di Google. Io stesso uso questa strategia in my Google Adwords dashboard.

È tuttavia possibile scrivere la libreria personalizzata e collegarsi direttamente al servizio. Di seguito è riportato un codice di sviluppo da un progetto che ho scritto alcuni mesi fa. Anche se non funziona immediatamente (dal momento che si tratta di un controller che fa parte di un'applicazione più grande), dovrebbe aiutarti a capire il flusso che la biblioteca di Google si prende cura di te.

namespace Application; 

class Controller_API_Google_Youtube extends Controller_API { 
    public function read() { 
     $scope = "https://www.googleapis.com/auth/youtube"; 
     $this->doOauth($scope); 
    } 

    function doOauth($scope) { 

     $oauth2Credentials = JSON_File::load(__DIR__ . DIRECTORY_SEPARATOR . 'Config.json'); 

     $paths = array(
      'token' => 'https://accounts.google.com/o/oauth2/token', 
      'auth' => "https://accounts.google.com/o/oauth2/auth" 
     ); 

     $refreshtime = 300; 

     if (isset($_GET['code'])) { 
      // Get access code 
      $query = $_GET; 
      unset($query['code']); 
      if (count($query) > 0) { 
       $query = '?' . http_build_query($query); 
      } else { 
       $query = ''; 
      } 

      $client = \PowerTools\HTTP_Client::factory(
         array(
          'maps' => array(
           'url' => $paths['token'], 
           'returntransfer' => 1, 
           'post' => true, 
           'postfields' => array(
            'code' => $_GET['code'], 
            "client_id" => $oauth2Credentials['client_id'], 
            "client_secret" => $oauth2Credentials['client_secret'], 
            "redirect_uri" => HTTP_PROTOCOL . URL_PATH . $query, 
            "grant_type" => "authorization_code" 
           ) 
          ) 
         ) 
      )->execute(); 
      $responses = $client->getResponses(); 
      $response = array_pop($responses); 
      $info = $response['maps']->getInfo(); 
      $content = $response['maps']->getContent(); 
      if ($info['http_code'] === 200) { 
       $output = JSON::decode($content); 
       $oauth2Credentials[$scope] = array(); 
       $oauth2Credentials[$scope]['expires'] = time() + $output['expires_in']; 
       $oauth2Credentials[$scope]['access_token'] = $output['access_token']; 
       $oauth2Credentials[$scope]['refresh_token'] = $output['refresh_token']; 
       file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Config.json', JSON::encode($oauth2Credentials)); 
       header("Location: " . HTTP_PROTOCOL . URL_PATH . $query); 
      } else { 
       echo "Something went wrong"; 
      } 
     } elseif (!isset($oauth2Credentials[$scope])) { 
      // Get auth code 

      header("Location: " . $paths['auth'] . '?' . http_build_query(
         array(
          "response_type" => "code", 
          "client_id" => $oauth2Credentials['client_id'], 
          "redirect_uri" => HTTP_PROTOCOL . DOMAIN_PATH, 
          "scope" => $scope 
         ) 
      )); 
     } elseif ($oauth2Credentials[$scope]['expires'] - $refreshtime < time()) { 
      // Refresh access code 

      $client = \PowerTools\HTTP_Client::factory(
         array(
          'maps' => array(
           'url' => $paths['token'], 
           'returntransfer' => 1, 
           'post' => true, 
           'postfields' => array(
            "client_id" => $oauth2Credentials['client_id'], 
            "client_secret" => $oauth2Credentials['client_secret'], 
            "refresh_token" => $oauth2Credentials[$scope]['refresh_token'], 
            "grant_type" => "refresh_token" 
           ) 
          ) 
         ) 
      )->execute(); 
      $responses = $client->getResponses(); 
      $response = array_pop($responses); 
      $info = $response['maps']->getInfo(); 
      $content = $response['maps']->getContent(); 
      if ($info['http_code'] === 200) { 
       $output = JSON::decode($response['maps']->getContent()); 
       $oauth2Credentials[$scope]['expires'] = time() + $output['expires_in']; 
       $oauth2Credentials[$scope]['access_token'] = $output['access_token']; 
       file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . 'Config.json', JSON::encode($oauth2Credentials)); 
       $this->read(); 
      } else { 
       $this->output = array("error" => "Something went wrong"); 
      } 
     } else { 
      $this->doSomethinguseful($oauth2Credentials, $scope); 
     } 
     return $this; 
    } 


    function doSomethinguseful($oauth2Credentials, $scope) { 
     // https://developers.google.com/youtube/v3/sample_requests?hl=nl 
     $client = \PowerTools\HTTP_Client::factory(
        array(
         'maps' => array(
          'useragent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13', 
          'url' => 'https://www.googleapis.com/youtube/v3/channels?part=contentDetails&mine=true', 
          'returntransfer' => true, 
          'httpheader' => array(
           'Authorization: Bearer ' . $oauth2Credentials[$scope]['access_token'], 
           'Accept-Encoding: gzip, deflate' 
          ) 
         ) 
        ) 
     )->execute(); 
     $responses = $client->getResponses(); 
     $response = array_pop($responses); 
     $content = $response['maps']->getContent(); 
     $this->output = JSON::decode(gzdecode($content)); 
    } 
} 
+0

Questa soluzione funziona, non è un problema e ho provato questo metodo anche prima, ma voglio autenticarmi senza l'accesso a Internet dal lato client. E anche usarlo con un'attività programmata (cron), quindi ho bisogno di farlo funzionare con un certificato. – global

+0

@global: senza accesso a Internet dal lato client? Che cosa vuoi fare esattamente il tuo client se non ha accesso a Internet? Con cosa comunica e quale parte della tua app dovrebbe comunicare con i servizi di Google? –

+0

Il client ha accesso alla intranet locale e anche a Internet, ma ciò non dovrebbe essere necessario perché il processo deve essere eseguito in background dal server che ha accesso a Internet. – global

-1

Sembra che tu stia incontrando un problema che ho avuto anch'io.

La chiamata a Google_Auth_AssertionCredentials richiede in realtà più parametri di quelli inviati per funzionare con un account di servizio. (Almeno, lo ha fatto nel mio caso.)

È necessario passare abbastanza parametri per includere sub (quale utente per eseguire azioni in base a).

Senza questo, ho sempre avuto un accesso negato. Questo chiaramente non è ovvio, dal momento che c'è stata anche una funzione aggiunta alla libreria php, , che dovrebbe configurare una connessione client per l'account di servizio, ma interrompe perché non imposta sub neanche.

vedi codice a lavorare qui: Google php client library loadServiceAccountJson broken - fix enclosed

+0

Perché è stato downvoted? –

Problemi correlati