Google API BadAuthentication error with Zend gdata - php

I am using gdata to add contacts to my gmail account using the Contact API. When I run the code on my development box as localhost, everything works fine. But when I move the code to a production server (www.somedomain.com) I get "ERROR:Authentication with Google failed. Reason: BadAuthentication".
Here's my code:
<?php
// load Zend Gdata libraries
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Http_Client');
Zend_Loader::loadClass('Zend_Gdata_Query');
Zend_Loader::loadClass('Zend_Gdata_Feed');
// set credentials for ClientLogin authentication
$user = "something#gmail.com";
$pass = "somepassword";
try {
// perform login and set protocol version to 3.0
$client = Zend_Gdata_ClientLogin::getHttpClient(
$user, $pass, 'cp');
$gdata = new Zend_Gdata($client);
$gdata->setMajorProtocolVersion(3);
// create new entry
$doc = new DOMDocument();
$doc->formatOutput = true;
$entry = $doc->createElement('atom:entry');
$entry->setAttributeNS('http://www.w3.org/2000/xmlns/' ,
'xmlns:atom', 'http://www.w3.org/2005/Atom');
$entry->setAttributeNS('http://www.w3.org/2000/xmlns/' ,
'xmlns:gd', 'http://schemas.google.com/g/2005');
$entry->setAttribute('xmlns', 'http://www.w3.org/2005/Atom');
$entry->setAttribute('xmlns:gd', 'http://schemas.google.com/g/2005');
$entry->setAttribute('xmlns:gContact', 'http://schemas.google.com/contact/2008');
$doc->appendChild($entry);
// add name element
$name = $doc->createElement('gd:name');
$entry->appendChild($name);
$fullName = $doc->createElement('gd:fullName', 'Jack Frost');
$name->appendChild($fullName);
// add email element
$email = $doc->createElement('gd:email');
$email->setAttribute('address' ,'jack.frost#example.com');
$email->setAttribute('rel' ,'http://schemas.google.com/g/2005#home');
$entry->appendChild($email);
// add org name element
$org = $doc->createElement('gd:organization');
$org->setAttribute('rel' ,'http://schemas.google.com/g/2005#work');
$entry->appendChild($org);
$orgName = $doc->createElement('gd:orgName', 'Winter Inc.');
$org->appendChild($orgName);
//add to Friends list
$group = $doc->createElement('gContact:groupMembershipInfo');
$group->setAttribute('deleted' ,'false');
$group->setAttribute('href' ,'http://www.google.com/m8/feeds/groups/' .urlencode($user) . '/base/[groupid]');
//addd to my contacts
$entry->appendChild($group);
$group = $doc->createElement('gContact:groupMembershipInfo');
$group->setAttribute('deleted' ,'false');
$group->setAttribute('href' ,'http://www.google.com/m8/feeds/groups/' .urlencode($user) . '/base/6'); //adds to Friends
$entry->appendChild($group);
// insert entry
$entryResult = $gdata->insertEntry($doc->saveXML(),
'http://www.google.com/m8/feeds/contacts/default/full');
echo '<h2>Add Contact</h2>';
echo 'The ID of the new entry is: ' . $entryResult->id;
echo 'The link is: ".$entryResult->getLink('edit')."";
} catch (Exception $e) {
die('ERROR:' . $e->getMessage());
}
?>
Should I be using OAuth for Services instead? I haven't been able to find documentation on how to do this with Zend Gdata.
EDIT - ANSWER FOUND:
Ok - I still have a question about a better auth method but I figured out what the issue was in this case. Google was suspicious of my application logging in. When I checked gmail, I had received the following:
Hi Info,
Someone recently used your password to try to sign in to your Google Account [someone]#gmail.com. This person was using an application such as an email client or mobile device.
We prevented the sign-in attempt in case this was a hijacker trying to access your account. Please review the details of the sign-in attempt:
Saturday, November 2, 2013 9:43:52 PM UTC
IP Address: [xxx.xxx.xx.xxx] ([xxx.xxx.xx.xxx].unifiedlayer.com.)
Location: Unknown
If you do not recognize this sign-in attempt, someone else might be trying to access your account. You should sign in to your account and reset your password immediately.
Reset password
If this was you, and you are having trouble accessing your account, complete the troubleshooting steps listed at http://support.google.com/mail?p=client_login
Sincerely,
The Google Accounts team
I went into gmail security (through the link provided) and was able to authorize the app. Problem solved. Works perfectly now.
I'd still like some pointers on how to use my Client ID, Service Account and Private Key with Zend (if possible). I have connected using the Google API php library but I can't see how to use this within the Zend framework.

On my side, I solved the problem by entering my full email address as username (username#gmail.com).
Previously, I tried to access to my account only with the username...

Related

QuickBooks PHP API - Can't get through the oAuth process again

First off: I'm using https://github.com/consolibyte/quickbooks-php
I accidentally disconnected the APP from the "Apps" page in an attempt to reconnect (get new auth creds), but it appears that was a mistake.
So now I'm trying to go through the authorization process again but I'm getting an error when I click the "Connect to QuickBooks" button on the "docs/example_app_ipp_v3/" page as described in the Quick-Start guide.
Is there something I'm missing here? I can still query through the API explorer, but I can't seem to get any data back when I use $InvoiceService->query in the code (just returns false).
//get invoice info
require_once '../includes/quickbooks-php/config.php';
// Set up the IPP instance
$IPP = new QuickBooks_IPP($dsn);
// Get our OAuth credentials from the database
$creds = $IntuitAnywhere->load($the_username, $the_tenant);
//error_reporting(0);
//ini_set('display_errors', 1);
// Tell the framework to load some data from the OAuth store
$IPP->authMode(
QuickBooks_IPP::AUTHMODE_OAUTH,
$the_username,
$creds);
// This is our current realm
$realm = $creds['qb_realm'];
// Load the OAuth information from the database
if ($Context = $IPP->context())
{
// Set the IPP version to v3
$IPP->version(QuickBooks_IPP_IDS::VERSION_3);
$CustomerService = new QuickBooks_IPP_Service_Customer();
$InvoiceService = new QuickBooks_IPP_Service_Invoice();
$ItemService = new QuickBooks_IPP_Service_Item();
$PaymentService = new QuickBooks_IPP_Service_Payment();
$invoice_query = $InvoiceService->query($Context, $realm, "SELECT *, Line.* FROM Invoice WHERE Id = '" .QuickBooks_IPP_IDS::usableIDType($main_invoice['qb_invoice_id']). "'");
$this_invoice = array();
var_dump($invoice_query);
if (count($invoice_query)){
foreach ($invoice_query as $Invoice){
//do stuff with invoice here
}
}
}
I'm getting bool(false) from the var_dump($invoice_query) even though it gets through the if($Context = $IPP->context())
Then when I visit the "docs/example_app_ipp_v3/" page with nothing but the config updated to my current auth credentials the "Connect to Quickbooks" button (html below) takes me to the 404 page.
<ipp:connecttointuit>Connect with QuickBooks</ipp:connecttointuit>
Are you POSITIVE that your App Token and other credentials are correct in the config.php file? If they are sandbox/dev tokens, please post the config file.
Are you POSITIVE that the URLs in your configuration file are correct? If they are sandbox/dev, please post them.
Is $sandbox set to TRUE or FALSE? Does that correspond to the tokens you're using?

Moodle API create user, generate password and email user

I am trying to create a new user in Moodle via the Web service API (version 2.7.1+ (Build: 20140829). I want to auto-generate the password and notify the user via email about his new account.
When I create a user via GUI there is a checkbox for doing exactly that: generating password and notifying user via email.
However, when I create a user via the API I do not know how to force password generation and the email notification. Unfortunately I cannot find anything in the Moodle API about how to automatically send email after user creation.
private function createUser($firstName, $lastName, $email){
$newUser = new stdClass();
$newUser->username = strtolower($email);
$newUser->password = getInitialPassword();
$newUser->firstname = $firstName ?: getRandomUsername();
$newUser->lastname = $lastName ?: '.';
$newUser->email = $email;
$newUser->preferences = array(array('type' =>'auth_forcepasswordchange', 'value' => true));
$users = array($newUser);
$params = array('users' => $users);
return post(buildServerUrl($create_user_command), $params);
}
Does anyone know how to do that?
it seems to be the same question asked at https://moodle.org/mod/forum/discuss.php?d=323422 , so here is the same answer:
"this improvement was introduced in 3.0, you may be interested in MDL-51182, it seems simple to backport."
Kind regards,
Daniel

Google Admin SDK PHP cannot create user. Not Authorized

I'm having a problem implementing Google Admin SDK in PHP. It always give error
Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST
https://www.googleapis.com/admin/directory/v1/users: (403) Not Authorized to access this
resource/api' in ..\google-api-php-client\src\Google\Http\REST.php on line 79
Here is my code :
<?php
session_start();
/* * **********************************************
Make an API request authenticated with a service
account.
* ********************************************** */
set_include_path("google-api-php-client/src" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Directory.php';
/* * **********************************************
ATTENTION: Fill in these values! You can get
them by creating a new Service Account in the
API console. Be sure to store the key file
somewhere you can get to it - though in real
operations you'd want to make sure it wasn't
accessible from the webserver!
The name is the email address value provided
as part of the service account (not your
address!)
Make sure the Books API is enabled on this
account as well, or the call will fail.
* ********************************************** */
$client_id = 'my_client_id'; //Client ID
$service_account_name = 'email'; //Email Address
$key_file_location = 'key.p12'; //key.p12
if ($client_id == '<YOUR_CLIENT_ID>' || !strlen($service_account_name) || !strlen($key_file_location)) {
echo missingServiceAccountDetailsWarning();
}
$client = new Google_Client();
$client->setApplicationName("appname");
$service = new Google_Service_Directory($client);
/* * **********************************************
If we have an access token, we can carry on.
Otherwise, we'll get one with the help of an
assertion credential. In other examples the list
of scopes was managed by the Client, but here
we have to list them manually. We also supply
the service account
* ********************************************** */
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://www.googleapis.com/auth/admin.directory.user'), $key
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
/* * **********************************************
We're just going to make the same call as in the
simple query as an example.
* ********************************************** */
$familyName = filter_input(INPUT_GET, 'familyname');
$givenName = filter_input(INPUT_GET, 'givenname');
$password = filter_input(INPUT_GET, 'password');
$primaryEmail = filter_input(INPUT_GET, 'email');
$user = new Google_Service_Directory_User();
$name = new Google_Service_Directory_UserName();
$name->setFamilyName($familyName);
$name->setGivenName($givenName);
$user->setName($name);
$user->setHashFunction("MD5");
$user->setPrimaryEmail($primaryEmail);
$user->setPassword(hash("md5", $password));
$result = $service->users->insert($user);
There is no documentation and I'm very confused with this error.
I had a similar problem until I set the "sub" account on the credentials object which is the email address for the administrative user that you want to perform the API action as.
So in Google Apps Admin for your domain I assume you've created a user and added them to and admin role that has API access to users right? In your code above you just need to add (with correct email address of course):
$cred->sub = "adminuser#domain.com";
Add that right before:
$client->setAssertionCredentials($cred);
I did a full example for someone else that you might be able to reference too: https://gist.github.com/fillup/9fbf5ff35b337b27762a
I had a similar problem but found a solution to this by going through this blog
http://michaelseiler.net/2014/12/16/google-admin-sdk-api-with-php/
Assuming you have done all the necessary setting up on the Admin Console (i.e. delegating domain authority), then pay particular attention to the line
`$cred = new Google_Auth_AssertionCredentials($service_account_name, array('https://www.googleapis.com/auth/admin.directory.user'), $key);`
this should be:
`$user_to_impersonate = 'adminaccount#example.com';$scopes =array('https://www.googleapis.com/auth/admin.directory.user');$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
$scopes,
$key,
'notasecret', // Default P12 password
'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type
$user_to_impersonate);`
I changed that and boom....
I think i was receiving this error when i tried to query a user.
During the creation of the JWT_CLAIM portion of the assertion, you must specify a domain admin account that your service account can impersonate... this part was poorly documented, i thought.
i dont know exactly how the google php library does it, but i didnt see anywhere in your code where you specify that account email address. if you have looked at the oauth2 documentation, in the jwt_claim secion, there is an "additional claims" subsection that says:
To obtain an access token that grants an application delegated access to a resource, include the email address of the user in the JWT claim set as the value of the sub field.
I had to include that admin email account in the creation of my assertion before i could even query the directory.users API.
i apologize if this isnt helpful, but im not using the library for php, im building my own (with php).

Service Applications and Google Analytics API V3: Error 101 (net::ERR_CONNECTION_RESET)

I'm trying to get some info of my Google Analytics account using PHP. I already followed the steps for creating a Service Account in the Google Console API in this answer. I'm using the Google API Client for PHP.
This is the code I've got so far:
<?php
$path_to_src = 'src';
// These files are in /src, upload its contents to your web server
require_once $path_to_src . '/Google_Client.php';
require_once $path_to_src . '/contrib/Google_AnalyticsService.php';
$path_to_keyfile = '***'; //my private key
// Initialise the Google Client object
$client = new Google_Client();
// Your 'Product name'
$client->setApplicationName('My App Name');
$client->setAssertionCredentials(
new Google_AssertionCredentials(
'**', //gserviceaccount mail
array('https://www.googleapis.com/auth/analytics.readonly'),
file_get_contents($path_to_keyfile)
)
);
// Get this from the Google Console, API Access page
$client->setClientId('***'); // my cliente ID
$client->setAccessType('offline_access');
$analytics = new Google_AnalyticsService($client);
// create service and get data
$service = new Google_AnalyticsService($client);
// We have finished setting up the connection,
// now get some data and output the number of visits this week.
// Your analytics profile id. (Admin -> Profile Settings -> Profile ID)
$analytics_id = 'ga:****'; // my profile id
$lastWeek = date('Y-m-d', strtotime('-1 week'));
$today = date('Y-m-d');
try {
$results = $analytics->data_ga->get($analytics_id,
$lastWeek,
$today,'ga:visits');
echo '<b>Number of visits this week:</b> ';
echo $results['totalsForAllResults']['ga:visits'];
} catch(Exception $e) {
echo 'There was an error : - ' . $e->getMessage();
}
I've enabled the openssl extension in PHP:
When browsing to the location of the php script, I just get a almost forever loading and the following error:
I'm using PHP 5.4.7:
After debuging the Google API Client code, it looks like the script is breaking at this line:
if (!openssl_sign($data, $signature, $this->privateKey, "sha256"))
Anything below this line does not get called. Looks like the error happens in this line. Is there a incompatibility here, or something?
One thing for starters you should change:
You instantiate the AnalyticsService twice. Take out the one you're not using:
$service = new Google_AnalyticsService($client);
See if that helps your problem at all.

Zend Youtube API - Upload Videos on a Single Account?

I want to allow anyone register on my site, to upload their videos on my own youtube user channel.
I don't want them to comment any videos, or anything that requires their own login credentials.
Should I use: ClientLogin authorization ?
If so, how can I get a token so that I can allow my site to interact with my youtube channel account?
Any lights here will be greatly appreciated, since I'm kinda lost here.
I have accomplished this using ClientLogin. A basic class is below. This class returns an instance of Zend HTTP Client that is ready to make authenticated requests.
<?php
class GoogleAuthenticator {
public static function authenticate($logger) {
$tokenObj = new Token();
try {
$token = $tokenObj->get($token_name);
if(!empty($token)) {
//load a new HTTP client with our token
$logger->info('Using cached token: ' . $token);
$httpClient = new Zend_Gdata_HttpClient();
$httpClient->setConfig(array(
'maxredirects' => 0,
'strictredirects' => true,
'useragent' => 'uploader/v1' . ' Zend_Framework_Gdata/' . Zend_Version::VERSION
)
);
$httpClient->setClientLoginToken($token);
//attempt to use our token to make an authenticated request. If the token is invalid
// an exception will be raised and we can catch this below
$yt = new Zend_Gdata_YouTube($httpClient, 'uploader/v1', '', $youtube_api_key);
$query = new Zend_Gdata_YouTube_VideoQuery();
$query->setFeedType('top rated');
$query->setMaxResults(1);
$yt->getPlaylistListFeed(null, $query); //ignore the response!
} else {
$logger->info('Generating new HTTP client');
// Need to create a brand new client+authentication
$authenticationURL= 'https://www.google.com/youtube/accounts/ClientLogin';
$httpClient =
Zend_Gdata_ClientLogin::getHttpClient(
$username = YOUTUBE_USERNAME_PROD,
$password = YOUTUBE_PASSWORD_PROD,
$service = 'youtube',
$client = null,
$source = 'uploader/v1',
$loginToken = null,
$loginCaptcha = null,
$authenticationURL);
// get the token so we can cache it for later
$token = $httpClient->getClientLoginToken();
$tokenObj->destroy($token_name);
$tokenObj->insert($token, $token_name);
}
return $httpClient;
}catch(Zend_Gdata_App_AuthException $e) {
$tokenObj->destroy($token_name);
die("Google Authentication error: " . $e->getMessage());
}catch(Exception $e) {
$tokenObj->destroy($token_name);
die("General error: " . $e->getMessage());
}
} // authenticate()
} // GoogleAuthenticator
?>
You'll need to have these constants defined:
YOUTUBE_USERNAME_PROD
YOUTUBE_PASSWORD_PROD
Or modify the class to pass them in. The try/catch is needed because tokens can expire, so you need to a way to refresh them. Also, you need to make a dummy request to ensure the Token is valid even after you create it.
Keep in mind that YouTube (well, as of 2 years ago or so) prevented you from uploading a video more of than every 10 minutes, which makes your use-case pretty difficult. That is, you cannot allow multiple videos being uploaded on a single accounts behalf, more of than every 10 min. But YouTube might have lifted this since then. Good luck
Since I didn't find any complete solutions for API V3 in the documentation I've been exploring the Internet for a solution. In the end I ported the Python example to PHP and wrote a blog post about it for other people that have the same problem:
Uploading a video to youtube through api version 3 in PHP
This blogpost uses the Youtube V3 api with OAuth2 so you don't have to worry about it being deprecated. All other functions (ClientLogin, AuthSub and OAuth 1.0) in V2 are all deprecated as of April 20, 2012.

Categories