Cannot connect MyBusiness with google-api-php-client - php

my goal is to receive the locations of a specific account.
I know the followed all instructions:
I downloaded and installed the google client in php
API Samples
I downloaded and installed MyBusiness.php from here
Business Samples
I created the project in the developer console (https://console.developers.google.com)
I requested access for Google My Business API and I received confirmation of activation and I enabled the API from the console.
I followed the tutorial to receive information about the accounts from which they can retrieve information
Unfortunately I always get the same error and I do not know what to do after hours of testing:
"Request is missing required authentication credential Expected OAuth 2 access token, login cookies or another valid authentication credential"
$client = new Google_Client();
$client->setHttpClient($httpClient);
$client->setApplicationName("project_id");
$client->setDeveloperKey('DEVELOPER KEY');
$client->setAuthConfig(plugin_dir_path( __FILE__ ).'oauth.json');
$client->setScopes("https://www.googleapis.com/auth/plus.business.manage");
$service = new Google_Service_Mybusiness($client);
$accounts = $service->accounts->listAccounts();
How can i solve it?
What am i missing?

Related

Google Server-to-Server OAuth2 PHP example not working

I am following this example to get server-to-server access working between my PHP application and Google Cloud API's,
https://developers.google.com/api-client-library/php/auth/service-accounts. In particular, I need to access the Drive API.
When I run the application though I get the following error:
Google_Service_Exception : {
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
}
Here's what I have done:
Created a GCP project
Added a service account to the project, with domain wide delegation, and a set of keys
Enabled the Google Drive API in the project
In my G Suite account, under 'Manage API client access', I have added the Client ID of my service account, with the permission of https://www.googleapis.com/auth/drive
Have I missed a step?
Here's my code:
putenv('GOOGLE_APPLICATION_CREDENTIALS=my_storage/secure/my-app-service-account.json');
$client = new \Google_Client();
$client->setScopes(\Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->useApplicationDefaultCredentials();
$client->setSubject('my_email#my_domain.com');
$drive = new \Google_Service_Drive($client);
echo $drive->about->get();
The example does not include the setScopes() call, however I was getting a scope-related error without it. (The example is not based on the Drive API, so perhaps it's not required in that case?)
UPDATE: In the IAM settings for the GCP, I added the email address of the service account as a Project Owner, but that made no difference.
I found the problem.
In the setScopes() call above, the value passed needs to be the same as the value given when setting up the client in G Suite, in this case https://www.googleapis.com/auth/drive

Facebook graph login API reports "Error validating verification code" with matching redirect uri's

"Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request"
My app with fb login works great in my localhost env, but fails with the above on a live domain name flow.
facebook/graph-sdk 5.3.1 Facebook SDK for PHP
With the above sdk, login helper getLoginUrl() returns the following (decoded)
https://www.facebook.com/v2.2/dialog/oauth?client_id=###...&state=#a#b#c...&response_type=code&sdk=php-sdk-5.3.1&redirect_uri=https://my.live.domain.net/&scope=email
And Client OAuth Settings > Valid OAuth redirect URIs contains precicely
https://my.live.domain.net/
Has anyone else cleared this hurdle?

how to pass youtube api auth and permission response from server to client's webrowser

So I have a Python script that is being run on the server (PHP runs it). However, script has to authenticate user on youtube. When you run it localy it opens the browser, allows to authenticate and asks for permission. Everything works. When I allow users to run it on server, it will try to open the auth screen on server. I need to pass the response to the web browser.
Any ideas?
I use the auth script from the youtube api examples:
# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
# the OAuth 2.0 information for this application, including its client_id and
# client_secret. You can acquire an OAuth 2.0 client ID and client secret from
# the Google Developers Console at
# https://console.developers.google.com/.
# Please ensure that you have enabled the YouTube Data API for your project.
# For more information about using OAuth2 to access the YouTube Data API, see:
# https://developers.google.com/youtube/v3/guides/authentication
# For more information about the client_secrets.json file format, see:
# https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
CLIENT_SECRETS_FILE = "client_secrets.json"
# This variable defines a message to display if the CLIENT_SECRETS_FILE is
# missing.
MISSING_CLIENT_SECRETS_MESSAGE = """
WARNING: Please configure OAuth 2.0
To make this sample run you will need to populate the client_secrets.json file
found at:
%s
with information from the Developers Console
https://console.developers.google.com/
For more information about the client_secrets.json file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
""" % os.path.abspath(os.path.join(os.path.dirname(__file__),
CLIENT_SECRETS_FILE))
# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account.
YOUTUBE_READ_WRITE_SCOPE = "https://www.googleapis.com/auth/youtube"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE,
message=MISSING_CLIENT_SECRETS_MESSAGE,
scope=YOUTUBE_READ_WRITE_SCOPE)
storage = Storage("%s-oauth2.json" % sys.argv[0])
credentials = storage.get()
if credentials is None or credentials.invalid:
flags = argparser.parse_args()
credentials = run_flow(flow, storage, flags)
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
http=credentials.authorize(httplib2.Http()))
The server side webapp is quiet simple, it allows to choose script variation and couple settings, that's all.
When you are authenticating your user credentials in your server, you need to use Oauth2 (in google's case).
It took me some time understanding it in the beginning as well...
The meaning of OAuth2 is that you redirect the user to a login address provided by google, tell the service "look, after the user logged in, send the token to URL X" (your server). Your server gets some sort of token that represents the user authorizing your "app" to do stuff on his behalf.
Check out https://developers.google.com/api-client-library/python/auth/web-app
Specifically in your case - you'll need to implement the endpoint in the PHP (it needs to "listen" on an address if you get my drift)
If you don't really need user credentials and only need to access youtube API as any authenticated user, it is easier - you need to have your own credentials and do "server to server" explained here:
https://developers.google.com/api-client-library/python/auth/service-accounts

SurveyMonkey: Cannot access Token using OAuth

I'm new to OAuth and I need help in accessing the Survey Monkey API to get the auth token. I tried using login_with_surveymonkey.php code and changed the client_id, client_secret, and api_key (https://developer.surveymonkey.com/apps/mykeys). It is giving me this error message:
'it was not possible to open the OAuth access token URL: could not resolve the host domain "api.surveymonkey.net"'
I tried running it on our dev environment and the error returned changed: 'it was not possible to access the OAuth access token: it was returned an unexpected response status 401 Response: {"error_description": "Invalid client_id/client_secret/api_key", "error": "invalid_client"}'
However, when I used the io-docs (https://developer.surveymonkey.com/io-docs) using the same client_id, client_secret, and api_key, I was able to connect to retrieve a token. I have curl working on my local machine.
Am I missing something?
Thanks!
The IO Docs API console does not actually perform OAuth correctly and is unfortunately not a good model on how to do OAuth - we have a replacement coming very soon.
The source code for that PHP OAuth implementation looks good, so I would check the following things:
client_id is your Mashery username
client_secret is a 32 character long secret associated with the api key you are providing - you can view it here https://developer.surveymonkey.com/apps/mykeys
Edit: According to our logs, it looks like you've solved this problem, correct? I think you were providing the api_key as the client_secret.

Google Analytics API oauth exception "invalid_grant" with Service Account. Same code on two servers. Only one works

I'm querying the Analytics API via a Service Account.
I have written the code on the dev server and it works without issues.
When running the same code on the production server, it throws this:
Google_AuthException: Error refreshing the OAuth2 token, message: '{
"error" : "invalid_grant" }'
I've tried creating another Service account, and the behavior is the same.
The oAuth IETF draft (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-31) says this about the error:
invalid_grant
The provided authorization grant (e.g. authorization
code, resource owner credentials) or refresh token is
invalid, expired, revoked, does not match the redirection
URI used in the authorization request, or was issued to
another client.
Here is the code I've written:
$GA_CLIENT_ID = 'XX.apps.googleusercontent.com';
$GA_APP_EMAIL = 'XX#developer.gserviceaccount.com';
$GA_APP_NAME = 'XX';
$GA_KEY_FILE = 'XX';
// create client object and set app name
$client = new Google_Client();
$client->setApplicationName($GA_APP_NAME); // name of your app
// set assertion credentials
$client->setAssertionCredentials(
new Google_AssertionCredentials(
$GA_APP_EMAIL, // email you added to GA
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($GA_KEY_FILE) // keyfile you downloaded
));
// other settings
$client->setClientId($GA_CLIENT_ID); // from API console
$client->setAccessType('offline_access'); // this may be unnecessary?
// create service and get data
$service = new Google_AnalyticsService($client);
$result = $service->data_ga->get($ids, $startDate, $endDate, $metrics, $optParams);
return $result;
I've also tried a solution suggested here (https://groups.google.com/forum/?fromgroups#!topic/gs-discussion/3y_2XVE2q7U%5B1-25%5D) using authenticatedRequest() instead of Google_AnalyticsService:
$req = new Google_HttpRequest($apiUrl);
$resp = $client::getIo()->authenticatedRequest($req);
$result = json_decode($resp->getResponseBody(), true);
This alternative also works on the dev server, but not on the production one.
I am totally clueless on this one. Has anyone seen this/fixed it?
Thanks!
Apparently the problem was the system time being off. Worked by sync-ing via NTP with:
sudo ntpdate npt.ubuntu.com
sudo ntpdate pool.ntp.org
Edit
As #RafaSashi suggested below, the pool.ntp.org server is more reliable. Use that instead of ntp.ubuntu.com (which was the first working one I tried, thus the initial choice).
The invalid grant can also be caused if you use the wrong "ServiceAccountId". It should be the email associated with the client id in the service account client id in the google apis access page. You'd also have to add this user to the google analytics account that you're planning to access.
This tripped me up because I assumed the email address they were referring to was the email address of my google account, since I used the same google account to get api access as I do for google analytics. I know Vir's already figured his out, just thought I'd add this in case someone else comes across the same question and, like me, their computer seems to be in sync with NTP.
In addition to Valer's answer:
First, you’ll need to install NTP if it isn’t already installed. For Debian or Ubuntu, that would be this command:
sudo apt-get install ntp
For Redhat or CentOS, you’ll need to use this one:
yum install ntp
If the synchronization via npt.ubuntu.com doesn't work try :
sudo ntpdate pool.ntp.org
Resources
http://www.howtogeek.com/tips/how-to-sync-your-linux-server-time-with-network-time-servers-ntp/
https://www.digitalocean.com/community/tutorials/how-to-set-up-time-synchronization-on-ubuntu-12-04
There are two major reasons for invalid_grant error which you have to take care prior to the POST request for Refresh Token and Access Token.
Request header must contain "content-type: application/x-www-form-urlencoded"
Your request payload should be url encoded Form Data, don't send as json object.
RFC 6749 OAuth 2.0 defined invalid_grant as:
The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.
I found another good article, here you will find many other reasons for this error.
https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35
Google Playground is best tool which help you how to send request.
https://developers.google.com/oauthplayground

Categories