YouTube Data API: authenticate as a resource owner

631 Views Asked by At

I have a task to import video details of videos, uploaded on YouTube.

I have an account, that is the video owner. I have setup credentials in the console: https://console.developers.google.com/project/XXXXX/apiui/credential. I have created OAuth Service Account there.

Later in the script I am using the code from documentation (v3 version of the API):

    $credentials = new Google_Auth_AssertionCredentials(
        $clientEmail,
        [
            'https://www.googleapis.com/auth/youtube',
            'https://www.googleapis.com/auth/youtube.force-ssl',
            'https://www.googleapis.com/auth/youtube.readonly',
            'https://www.googleapis.com/auth/youtubepartner',
        ],
        $privateKeyContents
    );
    $this->client->setAssertionCredentials($credentials);

    /** @var Google_Auth_OAuth2 $auth */
    $auth = $this->client->getAuth();

    if ($auth->isAccessTokenExpired()) {
        $auth->refreshTokenWithAssertion();
    }

Authentication works ok. I've attached logger to Google Client and I can see Authorization: Bearer XXXXXXX header passed with each request.

But the problem is, that it seems, YouTube does not recognize this authentication as an authentication of an actual resource owner. For example, if I request Video Snippet, it is returned without tags (tags can be seen only by owner on some reason).

If I make the same request from here https://developers.google.com/youtube/v3/docs/videos/list?hl=ru it works flawlessly.

What can be the problem?

The request in logs looks like this:

[2015-06-08 14:50:02] name.DEBUG: OAuth2 authentication [] []
[2015-06-08 14:50:02] name.DEBUG: cURL request {"url":"https://www.googleapis.com/youtube/v3/playlists?part=id%2Csnippet&channelId=XXXXXXXXXXXX&maxResults=50","method":"GET","headers":{"authorization":"Bearer ya29.XXXXX-XXXXXX","accept-encoding":"gzip"},"body":null} []

This differs from what I can see if tracing the request Google Javascript client makes on Documentation page. The domain is different, Javascript client passes more headers etc.

How do I make it work with PHP?

2

There are 2 best solutions below

1
On

You should add onBehalfofContentOwner parameter to your request to show yourself as the content owner.

8
On

You seem to have been using Google Service Account credentails for authentication. The API call needs to be made after authenticating as "Client ID for web application" rather than a service account. After you have created a new set of credentials for web application, authenticate as follows:

$OAUTH2_CLIENT_ID = 'REPLACE_ME';
$OAUTH2_CLIENT_SECRET = 'REPLACE_ME';

$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
    FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);//This Uri should match exactly to what you had given in Google Developer Console while generating Client ID/Secret

// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);

if (isset($_GET['code'])) {
  if (strval($_SESSION['state']) !== strval($_GET['state'])) {
    die('The session state did not match.');
  }

  $client->authenticate($_GET['code']);
  $_SESSION['token'] = $client->getAccessToken();
  header('Location: ' . $redirect);
}

Hope this resolves your problem.