I'm trying to access date using the Springpad API.
If I use the following link:
http://springpadit.com/api/blocks/all?limit=1&text=HARRY+POTTER
I have no problem getting 2 recent results with the search term "J K Rowlings'.
I wrote the following code to do the same thing after authorizing my server:
$api_url = "http://springpadit.com/api/";
$query = $_GET['query'];
$param = array('limit'=>1, 'text'=>$query);
$temp = http_build_query($param,"","&");
$url = $api_url."blocks/all?".$temp;
session_start();
// In state=1 the next request should include an oauth_token.
// If it doesn't go back to 0
if(!isset($_GET['oauth_token']) && $_SESSION['state']==1) $_SESSION['state'] = 0;
try {
$oauth = new OAuth($conskey,$conssec,OAUTH_SIG_METHOD_HMACSHA1,OAUTH_AUTH_TYPE_URI);
$oauth->enableDebug();
if(!isset($_GET['oauth_token']) && !$_SESSION['state']) {
$request_token_info = $oauth->getRequestToken($req_url);
$_SESSION['secret'] = $request_token_info['oauth_token_secret'];
$_SESSION['state'] = 1;
header('Location: '.$authurl.'?oauth_token='.$request_token_info['oauth_token'].'&oauth_token_secret='.$_SESSION['secret']);
exit;
} else if($_SESSION['state']==1) {
$oauth->setToken($_GET['oauth_token'],$_SESSION['secret']);
$access_token_info = $oauth->getAccessToken($acc_url);
$_SESSION['state'] = 2;
$_SESSION['token'] = $access_token_info['oauth_token'];
$_SESSION['secret'] = $access_token_info['oauth_token_secret'];
}
$oauth->setToken($_SESSION['token'],$_SESSION['secret']);
$oauth->fetch($url);
$json = json_decode($oauth->getLastResponse(),true);
print_r($json['blocks']);
} catch(OAuthException $E) {
print_r($E);
}
This should let you create the same query and retrieve the data by using the following link:
http://xrefpro.com/CRM/index.php?query=HARRY+POTTER
All I get is an empty array for my results. What am I doing wrong here??
The springpad api call "/api/blocks/all" is a global search across all users public data. It does not require auth. There does seem to be a bug with the api that causes that search to not work if you are logged in. You can test this by logging out of springpad and hitting
http://springpadit.com/api/blocks/all
and then try it when logged in.
I imagine what is happening is it is trying to find a block with that text in your own account. I am an employee at springpadit.com, we will look into fixing that bug with global queries. For now though, don't bother with oauth for a global query.
If you want to search your own account, use oauth and query
http://springpadit.com/api/users/me/blocks?limit=1&text=Thor
The response won't have a "blocks" node, so just change the print to
print_r($json);
Related
I got a warning email from Google reminding me of Google+'s EOL which is supposed to break my current "Login with Google", but I am unsure what exactly should I change.
Let me show you my (simplified) login code:
google-login.php
new class {
public function __construct() {
$state = mt_rand();
$client = new Google_Client();
$client->setApplicationName(Config::Google['app_name']);
$client->setClientId(Config::Google['id']);
$client->setClientSecret(Config::Google['secret']);
$client->setRedirectUri(sprintf('https://%s/members/google-callback.php', $_SERVER['HTTP_HOST']));
$client->setScopes(['profile', 'email']);
$client->setState($state);
$_SESSION['state'] = $state;
$url = $client->createAuthUrl(); // $url = https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=online&client_id=CLIENT_ID.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fread2me.online%2Fmembers%2Fgoogle-callback.php&state=1588245f23f2a&scope=profile%20email&approval_prompt=auto
header ("location: $url");
}
};
google-callback.php
new class {
private $newUser = false;
public function __construct() {
if (!isset($_GET['state']) || $_GET['state'] != $_SESSION['state'])
die('State mismatch.');
$client = new Google_Client();
$client->setApplicationName(Config::Google['app_name']);
$client->setClientId(Config::Google['id']);
$client->setClientSecret(Config::Google['secret']);
$client->setRedirectUri(sprintf('https://%s/members/google-callback.php', $_SERVER['HTTP_HOST']));
$client->setScopes(['profile', 'email']);
$plus = new Google_Service_Plus($client);
if (isset($_GET['code'])) {
$client->fetchAccessTokenWithAuthCode($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
if (!$client->getAccessToken() || $client->isAccessTokenExpired()) {
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$url = $client->createAuthUrl();
header ("location: $url");
}
try {
$me = $plus->people->get('me');
} catch (Google_Exception $e) {
\Rollbar::report_message($e->getMessage());
print_r($e->getMessage());
return;
}
$accessToken = $client->getAccessToken()['access_token'];
$email = $me->getEmails()[0]->getValue();
$name = $me->getDisplayName();
$avatar = $me->getImage()->getUrl();
$id = $me->getId();
if ($this->isEmailInSystem($email) === false) {
$this->newUser = true;
$this->addUser($email, $name, 'google', $accessToken, $id, $avatar);
}
header ("location: " . '/');
}
};
Now, I'm going through at what seems to be the up-to-date Sign In guide for PHP, but I am not sure what to change - any ideas?
Thanks
The best migration is to move from the Plus API to the People API, which provides access to the user's profile in a similar (tho not quite identical) way.
You would replace the creation of the $plus object with a new Goolge_Service_PeopleService object. Something like
$people = new Google_Service_PeopleService( $client );
Getting the profile is more involved since you need to specify which fields from the profile you want to get. But you might do it something like
$profile = $people->people->get(
'people/me',
array('personFields' => 'names,emailAddresses,photos')
);
The first parameter needs to be "people/me" to specify that you're requesting the authorized user's profile.
The second is an array of query parameters. You need to specify the "personFields" that you want from the list of what is available (scroll down on this page till you see the description of the available fields) and specify this as a comma separated list in a string. In my example above, I illustrate getting the name, email addresses, and photos. But consult the list and experiment.
The exact fields you get from the result in $profile will be different than those you got from $plus, but they should match the fields you requested. Check the values and exactly how they're structured.
I ran into the same issue as Google+ APIs shutting down on March 7, 2019.
Make sure Google People API is enable in your google console
I used google-api-php-client Library.
Once you have an access token here is code to get the person object using people API
$accessToken = 'REPLACE_WITH_ACCESS_TOKEN';
$clientId = 'REPLACE_WITH_CLIENT_ID';
$clientSecret = 'REPLACE_WITH_CLIENT_SECRET';
$developerKey = 'REPLACE_WITH_DEVELOPER_KEY';
$client = new Google_Client();
$client->setApplicationName("Application Name");
$client->setClientId($clientId . '.apps.googleusercontent.com');
$client->setClientSecret($clientSecret);
$client->setDeveloperKey($developerKey);
$client->setScopes(['https://www.googleapis.com/auth/userinfo.email','https://www.googleapis.com/auth/userinfo.profile']);
$client->setAccessToken($accessToken);
$guzzleClient = new \GuzzleHttp\Client(array( 'curl' => array( CURLOPT_SSL_VERIFYPEER => false, ), ));
$client->setHttpClient($guzzleClient);
$people = new Google_Service_PeopleService( $client );
if ($client->getAccessToken()) {
try {
$me = $people->people->get(
'people/me',
array('personFields' => 'emailAddresses,names,photos')
);
$id = preg_replace('/[^0-9]/', '', $me->getResourceName());
$email = $me->getEmailAddresses()[0]->value;
$name = $me->getNames()[0]->displayName;
$avtar = $me->getPhotos()[0]->getUrl();
} catch (Google_Exception $e) {
// error
echo $e->getMessage();
}
}
I also disabled Google+ API to make sure the application is not using it anymore anywhere.
With latest version of Google API PHP Client you can fetch profile details from Google_Client object itself.
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
$attributes = $client->verifyIdToken($token['id_token'], GOOGLE_CLIENT_ID);
print_r($attributes);
Refer this article.
Obviously, the lines
$plus = new Google_Service_Plus($client);
and
$me = $plus->people->get('me');
You need to use google email API, see https://developers.google.com/gmail/api/quickstart/php , so the first line will be
$service = new Google_Service_Gmail($client);
and second ... hmmm ... not sure there WILL be any avatar after removing of google plus ...
In extension to my question - https://stackoverflow.com/q/36847384/658209
I was thinking of using OAuth1Session from requests_oauthlib to retrieve access token and access token secret value. I want to do something similar to what is being done in below example:
<?php
/**
* Example of OAuth authorization n using Admin account via Magento REST API.
*/
$callbackUrl = "http://yourhost/oauth_admin.php";
$temporaryCredentialsRequestUrl = "http://magentohost/oauth/initiate?oauth_callback=" .
urlencode($callbackUrl);
$adminAuthorizationUrl = 'http://magentohost/admin/oauth_authorize';
$accessTokenRequestUrl = 'http://magentohost/oauth/token';
$apiUrl = 'http://magentohost/api/rest';
$consumerKey = 'yourconsumerkey';
$consumerSecret = 'yourconsumersecret';
session_start();
if (!isset($_GET['oauth_token']) && isset($_SESSION['state']) && $_SESSION['state'] == 1) {
$_SESSION['state'] = 0;
}
try {
$authType = ($_SESSION['state'] == 2) ? OAUTH_AUTH_TYPE_AUTHORIZATION :
OAUTH_AUTH_TYPE_URI;
$oauthClient = new OAuth($consumerKey, $consumerSecret,
OAUTH_SIG_METHOD_HMACSHA1, $authType);
$oauthClient->enableDebug();
if (!isset($_GET['oauth_token']) && !$_SESSION['state']) {68
$requestToken = $oauthClient->getRequestToken($temporaryCredentialsRequestUrl);
$_SESSION['secret'] = $requestToken['oauth_token_secret'];
$_SESSION['state'] = 1;
header('Location: ' . $adminAuthorizationUrl . '?oauth_token=' . $requestToken['oauth_token']);
exit;
} else if ($_SESSION['state'] == 1) {
$oauthClient->setToken($_GET['oauth_token'], $_SESSION['secret']);
$accessToken = $oauthClient->getAccessToken($accessTokenRequestUrl);
echo "oauth_token:".$accessToken['oauth_token']."<br/>";
echo "oauth_token_secret:".$accessToken['oauth_token_secret'];
exit;
} else {
echo "authorisation failed";
}
} catch (OAuthException $e) {
print_r($e);
}
I have come up with the following code:
class Magento_Oauth_Admin(restful.Resource):
def get(self):
return render_template('magentosetup.html')
def post(self):
consumer_key=request.form.get('consumer_key')
consumer_secret=request.form.get('consumer_secret')
magentourl=request.form.get('magentourl')
session['magentourl']=magentourl
callbackurl = api.url_for(Magento_Access_Token)
temporary_credentials_request_url = '{magentourl}/oauth/initiate?{callbackurl}'.format(magentourl, urllib.urlencode(
dict(oauth_callback=callbackurl)))
admin_authorization_url = '{magentourl}/admin/oauth_authorize'.format(magentourl)
oauth_session = OAuth1Session(consumer_key, client_secret=consumer_secret, callback_uri=callbackurl)
# First step, fetch the request token.
fetch_response = oauth_session.fetch_request_token(temporary_credentials_request_url)
session['resource_owner_key'] = fetch_response.get('oauth_token')
session['resource_owner_secret'] = fetch_response.get('oauth_token_secret')
# Second step. Follow this link and authorize
authorization_url = oauth_session.authorization_url(admin_authorization_url)
return redirect(authorization_url)
class Magento_Access_Token(restful.Resource):
""" The user has been redirected back from the provider to the registered
callback URL. With this redirection comes an authorization code included
in the redirect URL. We will use that to obtain an access token."""
def get(self):
access_token_request_url = '{magentourl}/oauth/token'.format(session['magentourl'])
verifier = request.args.get('oauth_verifier')
oauth = OAuth1Session(consumer_key,
client_secret=consumer_secret,
resource_owner_key=session['resource_owner_key'],
resource_owner_secret=session['resource_owner_secret'],
verifier=verifier)
oauth_tokens = oauth.fetch_access_token(access_token_request_url)
resource_owner_key = oauth_tokens.get('oauth_token')
resource_owner_secret = oauth_tokens.get('oauth_token_secret')
return render_template('magentosetupcomplete.html')
api.add_resource(Magento_Oauth_Admin,"/v2/generateaccesstoken/",endpoint="generateaccesstoken")
api.add_resource(Magento_Access_Token,"/v2/callback/",endpoint="callback")
I am not sure how to handle callback and redirects instead of asking the user to go to authorization_url and then paste the redirect url
EDIT: After reading Robbie's comment I have updated my code and split it into 2 endpoints. So now flow of my application is something like:
User goes to magentosetup.html and enters consumer token,secret and their magento instance url. They submit this form
We get the credentials from above form into Magento_Oauth_Admin post and then we trigger the oAuth dance to generate access token and secret.
Once the access token is generated I will store it somewhere(not written that code here)
My question now is in the final step (after the provider redirects user to consumer API, after user authorization), will I be able to redirect the user to magentosetupcomplete.html by using return render_template('magentosetupcomplete.html') to confirm to the user that the access token has been generated and saved. I am asking this because the /callback endpoint has been called from magento. I am not sure what the flow of control is in this situation.
I'm a little confused about the flow I need to use if trying to connect to a remote Wordpress WP-API from another server (in this case another WP instance on the same server). I am using the PECL oAuth package, and most of the code I gathered up from the docs at https://secure.php.net/manual/en/class.oauth.php.
This is tied into a wordpress save hook like this, so every time someone saves a post on SITE A, it will attempt to send some info over to SITE B:
add_action( 'save_post', 'CrossPollinate_Save',10,3);
Inside CrossPollinate_Save is this:
$client_key = "....";
$client_secret = "....";
$request_token_endpoint = "http://..../oauth1/request";
$authorize_endpoint = "http://..../oauth1/authorize";
$access_endpoint = "http://..../oauth1/access";
$callback = $_SERVER['REQUEST_URI'];
$request_token = ""; //populated later
$request_token_secret = ""; //populated later
//STEP 1
$oauth = new OAuth($client_key, $client_secret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_AUTHORIZATION);
$request_token_info = $oauth->getRequestToken($request_token_endpoint);
if(!empty($request_token_info)) {
logToFile("Response from getRequestToken", $request_token_info);
} else {
logToFile("Failed fetching request token: ", $oauth->getLastResponse());
}
$request_token = $request_token_info["oauth_token"];
$request_token_secret = $request_token_info["oauth_token_secret"];
logToFile("request_token is: ", $request_token);
logToFile("request_token_secret is: ", $request_token_secret);
//STEP 2
$oauth->setToken($request_token, $request_token_secret);
$access_token_info = $oauth->getAccessToken($authorize_endpoint."?oauth_callback=".$callback);
if(!empty($access_token_info)) {
logToFile("Got access token! ", $access_token_info);
} else {
logToFile("Failed fetching access token: " . $oauth->getLastResponse());
}
I get an oauth_token and a oauth_token_secret from "step 1", great, that part works! When step 2 fires it ends up returning with a response that contains the markup for the login page. How do I tell oAuth to skip that step and just send the access token back to the redirect page?
I don't think there's a way around having to do the full 3-legged auth. I've found nothing to the contrary anyway and have just accepted that I'll have to do the redirect after getting the initial tokens.
Users on my website can login to Twitter and post their status on my website and twitter at once. I'm using https://github.com/abraham/twitteroauth to connect to Twitter. Login and posting is performed on different pages of website.
This is login script:
public function loginTwitter() {
$twitter = new TwitterOAuth(
$this->getContext()->params['social']['twitter']['consumerKey'],
$this->getContext()->params['social']['twitter']['consumerSecret']
);
$request_token = $twitter->getRequestToken($this->link('//User:connectFromTwitter'));
// Saving to session (Nette Framework)
$twitterSession = $this->getContext()->session->getSection('twSes');
$twitterSession->oauth_request_token = $token = $request_token['oauth_token'];
$twitterSession->oauth_request_token_secret = $request_token['oauth_token_secret'];
if ($twitter->http_code == 200) {
$requestLink = $twitter->getAuthorizeURL($token);
$this->redirectUrl($requestLink);
} else {
echo 'Error';
}
}
This is callback script (posting works right after user has been logged in):
public function twitterOauth() {
// $_GET parameter oauth_verifier
$oauthVerifier = $this->getParam('oauth_verifier');
// Session section
$twitterSession = $this->getContext()->session->getSection('twSes');
$twitter = new TwitterOAuth(
$this->getContext()->params['social']['twitter']['consumerKey'],
$this->getContext()->params['social']['twitter']['consumerSecret'],
$twitterSession->oauth_request_token,
$twitterSession->oauth_request_token_secret
);
$access_token = $twitter->getAccessToken($oauthVerifier);
$twitterSession->access_token = $access_token;
$user_info = $twitter->get('account/verify_credentials');
// Saving to DB to be able to post without login
$tm = new TwitterUserManager();
if (!$tm->isInDatabase($this->getUser()->getId())) {
$tu = new TwitterUser();
$tu->setUser($this->loggedUser);
$tu->setOauthProvider('twitter');
$tu->setOauthUid("'".$user_info->id."'");
$tu->setUsername("'".$user_info->screen_name."'");
$tu->setOauthToken("'".$access_token['oauth_token']."'"); // Saving the access token for further posting
$tu->setOauthSecret("'".$access_token['oauth_token_secret']."'");
$tm->persist($tu);
}
$twitter->post('statuses/update', array('status' => 'Hello ' . date('d.m.Y H:i:s'))); // <== HERE IT WORKS
$this->redirect('User:socialConnect'); // Redirect to another page
}
This is posting function (User posts from any page):
public function postToTwitter() {
$twitterSession = $this->getContext()->session->getSection('twitter');
$twitter = new TwitterOAuth(
$this->getContext()->params['social']['twitter']['consumerKey'],
$this->getContext()->params['social']['twitter']['consumerSecret'],
$twitterSession->access_token['oauth_token'],
$twitterSession->access_token['oauth_token_secret']
);
return $twitter->post('statuses/update', array('status' => 'Hello' . date('d.m.Y H:i:s')));
}
When I use posting function I get this error:
stdClass(2) {
request => "/1/statuses/update.json" (23)
error => "Could not authenticate you." (27)
}
Thanks for help in advance.
EDIT: Solution:
Use this to connect to Twitter (save all info into DB):
http://framework.zend.com/manual/1.12/en/zend.oauth.introduction.html
Use this to post from any page:
http://framework.zend.com/manual/1.12/en/zend.service.twitter.html
Nice example:
http://www.joeyrivera.com/2010/twitter-api-oauth-authentication-and-zend_oauth-tutorial/
I always used the Zend-Framework-Component: http://framework.zend.com/manual/1.12/en/zend.service.twitter.html
I think it's simple and I could confirm, that it works. You just have to read through the tutorial (see link above).
I'm fairly new to the concept of OAuth and I'm trying to interact with the new Rdio API. I've managed to figure out the authentication using the PECL OAuth functions, but Rdio requires arguments to be passed in via POST and I can't figure out how that is done. The authentication works: the user is bounced to Rdio's site and asked to approve the application, and they are then returned to the site. After that, though, the request making calls to the API fails.
Here's some info on the Rdio API: http://developer.rdio.com/docs/REST/
Here's the code I have for authentication... the lines in italics are what I believe should make the call to the API requesting the method named "currentUser"
$req_url = 'http://api.rdio.com/oauth/request_token';
$authurl = 'https://www.rdio.com/oauth/authorize';
$acc_url = 'http://api.rdio.com/oauth/access_token';
$callback = 'http://localhost/test.php';
$api_url = 'http://api.rdio.com/1';
$conskey = 'vmu7x6u4rk8vae8dn28h';
$conssec = 'GrY7gF';
session_start();
if(!isset($_GET['oauth_token']) && $_SESSION['state']==1) $_SESSION['state'] = 0;
try {
$oauth = new OAuth($conskey,$conssec,OAUTH_SIG_METHOD_HMACSHA1,OAUTH_AUTH_TYPE_URI);
$oauth->enableDebug();
if(!isset($_GET['oauth_token']) && !$_SESSION['state']) {
$request_token_info = $oauth->getRequestToken($req_url);
$_SESSION['secret'] = $request_token_info['oauth_token_secret'];
$_SESSION['state'] = 1;
header('Location: '.$authurl.'?oauth_token='.$request_token_info['oauth_token'].'&oauth_callback='.urlencode($callback));
exit;
} else if($_SESSION['state']==1) {
$oauth->setToken($_GET['oauth_token'],$_SESSION['secret']);
$access_token_info = $oauth->getAccessToken($acc_url);
$_SESSION['state'] = 2;
$_SESSION['token'] = $access_token_info['oauth_token'];
$_SESSION['secret'] = $access_token_info['oauth_token_secret'];
}
$args = "method=currentUser";
$oauth->setToken($_SESSION['token'],$_SESSION['secret']);
$oauth->fetch("$api_url", $args);
$json = json_decode($oauth->getLastResponse());
print_r($json);
} catch(OAuthException $E) {
print_r($E);
}
The message I get back:
Warning: OAuth::fetch(http://api.rdio.com/1?oauth_consumer_key=vmu7x6u4rktv468vae8dn28h&oauth_signature_method=HMAC-SHA1&oauth_nonce=12606272174d85622ad26ce8.80381248&oauth_timestamp=1300587050&oauth_version=1.0&oauth_token=238zec5p4rpcpbfd8j36sjggz3jfsssybhxgcn9kvmmrmdxr3t4f2cnspt4dg5xf&oauth_signature=1mZhJ9AUbi0sm6qhNaAntumAckU%3D) [function.OAuth-fetch]: failed to open stream: HTTP request failed! HTTP/1.0 596
The problem is most likely that the arguments (method=currentUser) aren't being passed via POST properly. Does anyone have any idea how to do this using PECL's OAuth extensions?
In case anyone comes across this looking for the answer, here is what I found works:
To perform a POST OAuth signed request, you need to set the OAuth object to send using POST instead of GET by adding this method before the fetch() method:
$oauth->setAuthType(OAUTH_AUTH_TYPE_FORM);
Even if you're using the OAUTH_HTTP_METHOD_POST parameter in the fetch() method, the OAuth instance itself needs to have setAuthType(OAUTH_AUTH_TYPE_FORM) called on it first.
The code for the specific example I was citing is:
if(!isset($_GET['oauth_token']) && $_SESSION['state']==1) $_SESSION['state'] = 0;
$oauth = new OAuth($rdio_conskey,$rdio_conssec,OAUTH_SIG_METHOD_HMACSHA1,OAUTH_AUTH_TYPE_URI);
$oauth->enableDebug();
if(!isset($_GET['oauth_token']) && !$_SESSION['state']) {
$request_token_info = $oauth->getRequestToken($rdio_req_url);
$_SESSION['secret'] = $request_token_info['oauth_token_secret'];
$_SESSION['state'] = 1;
header('Location: '.$rdio_auth_url.'?oauth_token='.$request_token_info['oauth_token'].'&oauth_callback='.$callbackurl);
exit;
} else if($_SESSION['state']==1) {
$oauth->setToken($_GET['oauth_token'],$_SESSION['secret']);
$access_token_info = $oauth->getAccessToken($rdio_acc_url);
$_SESSION['state'] = 2;
$_SESSION['token'] = $access_token_info['oauth_token'];
$_SESSION['secret'] = $access_token_info['oauth_token_secret'];
}
$oauth = new OAuth($rdio_conskey, $rdio_conssec, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
$oauth->setToken($access_token_info['oauth_token'],$access_token_info['oauth_token_secret']);
$oauth->setAuthType(OAUTH_AUTH_TYPE_FORM);
$oauth->fetch($rdio_api_url, array("method" => "currentUser", "extras" => "username"), OAUTH_HTTP_METHOD_FORM);
$json = json_decode($oauth->getLastResponse());
print_r($json);
Using OAUTH_AUTH_TYPE_FORM is only a workaround.
Pecl's oauth extension version 1.2.3 has a bug; getRequestToken and getAccessToken use GET requests instead of POST as the RFC wants.
You can work around this bug by passing OAUTH_HTTP_METHOD_POST as 3rd parameter to getRequestToken and 4th parameter to getAccessToken. Yes, those parameters are undocumented.
Version 1.2.4 of pecl/oauth will default to POST.