0

I'm trying the following thing for quite a while now and am heavily struggling...

On a website, I first want to authenticate a user with his Google Account using OAuth. Therefore, I'm using this library. In order to get it working, I used $f3->set('AUTOLOAD','vendor/ikkez/f3-opauth/lib/opauth/'); to load the PHP files and then used the following code to create the routes and make the authentication possible:

$f3 = \Base::instance();
// load opauth config (allow token resolve)
$f3->config('vendor/ikkez/f3-opauth/lib/opauth/opauth.ini', TRUE);

// init with config
$opauth = OpauthBridge::instance($f3->opauth);

// define login handler
$opauth->onSuccess(function($data){
    header('Content-Type: text');

    //$data['credentials']['token'];
});

// define error handler
$opauth->onAbort(function($data){
    header('Content-Type: text');
    echo 'Auth request was canceled.'."\n";
    print_r($data);
});

So far so good, thats all working fine, once permission is granted from Google I get the correct callback, also including the login token.

Now the next step is, that after user gave permission for that (by authenticating), I want to check, if the user subscribed to a specific channel on Youtube (and afterwards saving that information to my DB, printing it at the first step would be enough though).

Now I did my homework for multiple hours in trying to figuring out how it works...

What I (in general found) is that the following curl request should give me the desired result:

curl \
  'https://youtube.googleapis.com/youtube/v3/subscriptions?part=snippet%2CcontentDetails&forChannelId=UC_x5XG1OV2P6uZZ5FSM9Ttw&mine=true&key=[YOUR_API_KEY]' \
  --header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
  --header 'Accept: application/json' \
  --compressed

I then tried to sent this curl request with PHP, substituting the API KEY with my Google API Key and "YOUR_ACCESS_TOKEN" with the token I got from OAUTH.... However, it's throwing an error, saying "request had insufficient authentication scopes"... That seems to be because when checking the PHP example from Google, I have to provide the Scopes I'm using - in my case https://www.googleapis.com/auth/youtube.readonly.

The PHP code provided by Google is the following:

<?php

/**
 * Sample PHP code for youtube.subscriptions.list
 * See instructions for running these code samples locally:
 * https://developers.google.com/explorer-help/guides/code_samples#php
 */

if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
  throw new Exception(sprintf('Please run "composer require google/apiclient:~2.0" in "%s"', __DIR__));
}
require_once __DIR__ . '/vendor/autoload.php';

$client = new Google_Client();
$client->setApplicationName('API code samples');
$client->setScopes([
    'https://www.googleapis.com/auth/youtube.readonly',
]);

// TODO: For this request to work, you must replace
//       "YOUR_CLIENT_SECRET_FILE.json" with a pointer to your
//       client_secret.json file. For more information, see
//       https://cloud.google.com/iam/docs/creating-managing-service-account-keys
$client->setAuthConfig('YOUR_CLIENT_SECRET_FILE.json');
$client->setAccessType('offline');

// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open this link in your browser:\n%s\n", $authUrl);
print('Enter verification code: ');
$authCode = trim(fgets(STDIN));

// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);

// Define service object for making API requests.
$service = new Google_Service_YouTube($client);

$queryParams = [
    'forChannelId' => 'UC_x5XG1OV2P6uZZ5FSM9Ttw',
    'mine' => true
];

$response = $service->subscriptions->listSubscriptions('snippet,contentDetails', $queryParams);
print_r($response);

This let's me run into a new issue... Trying to use this code, I'm getting the error, that Google_Client is not known as class... I then went ahead and installed Google Client with Composer and tried to use vendor/autoload.php in order to use the class.... However, when including the autoload.php, I get the error Fatal error: Cannot declare class Prefab, because the name is already in use... This seems to be the case, because the f3-opauth declares this Prefab class already and then the google apiclient tries to declare it again... However, I didn't manage to to include google apiclient without the autoload...

You see, I really tried a lot and I've been working on this for about 5-6 hours today, only getting that one API request to work and I don't know what else to try...

Any hint on how to get it working would be appreciated - if there's any hint on doing it a completely other way, I'd be willing to change it as well, as the project itself just started.

Summarizing, what I'm trying to do is the following: -> User can log in on Website with his Youtube/Google Account -> When authenticating, its checked, if the User is a Subscriber of a specific channel. Next step would be to also check, if he is a channel member of this speicific channel. Both information would need to be saved to database

-> after that, user can always log in into his account with Google again and in the database, you can find the information if the user is subscriber and/or channel member of this channel..

Thanks in advance!

nameless
  • 1,483
  • 5
  • 32
  • 78

1 Answers1

0

I'm not sure if this will help with your exact use case, but I've worked with Google APIs in the past with Fat-Free. I couldn't get it to work right off the bat, so I installed and got it working with the Google Client/API/SDK. Once I got that working, then I worked backwards to see if I could make it work with Fat-Free. One of the things that I noticed I was running into was missing fields in the Oauth request. access_type was one that got me as well as approval_prompt. I know that you said you've gotten your access token thus far, so it may not apply, but it could for future requests. Here's some example code I've got working to generate an oauth URL for Google Sign in, and then to process the request and make the call to the userinfo portion.

<?php 

class App_Auth {
    public static function generateOauthUrl() {
        $fw = Base::instance();
        $Oauth = new \Web\OAuth2();
        $Oauth->set('client_id', $fw->get('google.client_id'));
        $Oauth->set('scope', 'profile email');
        $Oauth->set('response_type', 'code');
        $Oauth->set('access_type', 'online');
        $Oauth->set('approval_prompt', 'auto');
        $Oauth->set('redirect_uri', $fw->SCHEME.'://' . $_SERVER['HTTP_HOST'] . $fw->BASE.'/oauthRedirect');
        return $Oauth->uri('https://accounts.google.com/o/oauth2/auth', true);
    }

    public static function processAuthCodeAndGetToken($auth_code) {
        $fw = Base::instance();
        $Oauth = new \Web\OAuth2();
        $Oauth->set('client_id', $fw->get('google.client_id'));
        $Oauth->set('client_secret', $fw->get('google.client_secret'));
        $Oauth->set('scope', 'profile email');
        $Oauth->set('access_type', 'online');
        $Oauth->set('grant_type', 'authorization_code');
        $Oauth->set('code', $auth_code);
        $Oauth->set('approval_prompt', 'auto');
        $Oauth->set('redirect_uri', $fw->SCHEME.'://' . $_SERVER['HTTP_HOST'] . $fw->BASE.'/oauthRedirect');
        return $Oauth->request('https://oauth2.googleapis.com/token', 'POST');
    }

    public static function getOauthUserInfo($access_token) {
        $Oauth_User_Info = new \Web\OAuth2();
        return $Oauth_User_Info->request('https://www.googleapis.com/oauth2/v2/userinfo', 'GET', $access_token);
    }

One other error that has bitten me in the backside was we would get our access token from Google and then store it in the database for subsequent requests. We would get that scopes error you mentioned request had insufficient authentication scopes. We eventually figured out that the access_token was longer than our database field (VARCHAR(32) if I remember right) so we needed to make our database field longer so it would store the whole thing.

Hopefully one of those triggers something for you to figure out your issue.

n0nag0n
  • 1,575
  • 1
  • 17
  • 25