Google Latitude and OAuth Signed requests - perl

I've written a script that authenticates against Google's OAuth API for Latitude, using Net::OAuth. It correctly authenticates (as I can successfully fetch data out of the API). However, when I try to add an historical entry, I get a 401 Unknown authorization header response. I'm using the following code:
my $location_data = $json->encode(\%data);
$request = Net::OAuth->request("protected resource")->new(
consumer_key => $c_key,
consumer_secret => $c_secret,
token => $token,
token_secret => $token_secret,
verifier => $verifier,
request_url => 'https://www.googleapis.com/latitude/v1/location',
request_method => 'POST',
signature_method => $s_method,
timestamp => time,
nonce => &nonce(),
extra_params => {
key => $s_key
}
);
$request->sign;
$ua->default_header("Authorization", $request->to_authorization_header);
$ua->default_header("Content-Type", "application/json");
my $res = $ua->post('https://www.googleapis.com/latitude/v1/location?key=' . $s_key,
Content => $location_data);
All of the variables are used in the fetch portion of the API, so I know those are all ok. I'm not sure if I'm using the correct URL to post against, and I've tried what's in the sample above, as well as $request->to_url.
Any suggestions would be greatly appreciated.

After some back and forth with the Latitude API team, it was determined that this error comes from the fact that the Content-Type is not actually being set to application/json. Changing the above code to:
$ua->default_header("Authorization", $request->to_authorization_header);
my $res = $ua->post('https://www.googleapis.com/latitude/v1/location?key=' . $s_key,
'Content-Type' => 'application/json',
Content => $location_data);
And everything works as expected.

Related

guzzle 6 post does not work

I am trying to submit a post with JSON content. I always get this message back:
"Client
error: POST
https://sandbox-api-ca.metrc.com//strains/v1/create?licenseNumber=CML17-0000001
resulted in a 400 Bad Request response: {"Message":"No data was
submitted."}"
(All keys and license number are sandbox. I changed keys slightly so auth wont work. )
here is my code
public function metrc()
{
$client = new Client();
$url = 'https://sandbox-api-ca.metrc.com//strains/v1/create?licenseNumber=CML17-0000001';
$request = $client->post($url, [
'headers' => ['Content-Type' => 'application/json'],
'json' => ['name' => "Spring Hill Kush"],
'auth' => ['kH-qsC1oJPzQnyWMrXjw0EQh812jHOX52ALfUIm-dyE3Wy0h', 'fusVbe4Yv6W1DGNuxKNhByXU6RO6jSUPcbRCoRDD98VNXc4D'],
]);
}
Your code is correct, it should works as expected. Seems that the issue is on the server side. Maybe the format of the POST request is not correct?
BTW, 'headers' => ['Content-Type' => 'application/json'] is unnecessary, Guzzle sets the header by itself automatically when you use json option.

Unable to get Response Parameters in Notification and Success url SOFORT API

public function sofyAction()
{
$args = [ 'config_key' => $this->getConfigKey() ];
$sofy = new Api($args);
$helper = $this->getServiceLocator()->get('ViewHelperManager')->get('ServerUrl');
$successUrl = $helper($this->url()->fromRoute('sofort_response'));
$params = [
'amount' => 1500,
'currency_code' => 'EUR',
'reason' => 'Vouhcer Order',
'success_url' => $successUrl,
'customer_protection' => false,
'notification_url' => 'MY_PRIVATE_RESPONSE_URL',
];
$trans = $sofy->createTransaction($params);
return $this->redirect()->toUrl($trans['payment_url']);
}
How to get response and transaction ID as given it API document in Notification URL and on success URL too , please unable to find any help or guide for it ?
The easiest way is to let Payum do notification related job for you. To do so you either:
have to create manually a notification token using Payum's token factory (I am not sure it is present in the Zend module, it is quite old). Use the token as notification_url. Nothing more. Sofort will send a request to that url and Payum does the rest.
Make sure the token factory is passed to a gateway object and later is injected to capture action object. Leave the notification_url field empty and Payum will generate a new one.
use your own url as notification one and add there all the info you need (as a query string). I wouldn't recommend it since you expose sensitive data and once could try to exploit it.
I solved it this way by appending ?trx=-TRANSACTION- with success and notification url and than in response i recieved Transaction id as parameter and later loaded TransactionData with that transactionId . Payum Token way wasn't working for me ! Obiously had to use its config key to create Payum/Sofort/Api isnstance,
REQUEST:
$args = [ 'config_key' => $sofortConfigKey ];
$sofortPay = new Api($args);
// ?trx=-TRANSACTION- will append transacion ID as response param !
$params = [
'amount' => $coupon['price'],
'currency_code' => $coupon['currency'],
'reason' => $coupon['description'],
'success_url' => $successUrl.'?trx=-TRANSACTION-',
'abort_url' => $abortUrl.'?trx=-TRANSACTION-',
'customer_protection' => false,
'notification_url' => '_URL_'.'?trx=-TRANSACTION-',
];
$transactionParams = $sofortPay->createTransaction($params);
return $this->redirect()->toUrl($transactionParams['payment_url']);
RESPONSE:
$args = [ 'config_key' => $configKey ];
$sofy = new Api( $args );
$transNumber = $this->getRequest()->getQuery('trx');
$fields = $sofy->getTransactionData($transNumber);
Took help from API document. Payum documentation is worst. SOFORT API DOC

JWT: Why am I always getting token_not_provided?

I am sending a PUT request to an API endpoint I have created. Using jwt, I am able to successfully register and get a token back.
Using Postman, my request(s) work perfectly.
I am using Guzzle within my application to send the PUT request. This is what it looks like:
$client = new \Guzzle\Http\Client('http://foo.mysite.dev/api/');
$uri = 'user/123';
$post_data = array(
'token' => eyJ0eXAiOiJKV1QiLCJhbGc..., // whole token
'name' => 'Name',
'email' => name#email.com,
'suspended' => 1,
);
$data = json_encode($post_data);
$request = $client->put($uri, array(
'content-type' => 'application/json'
));
$request->setBody($data);
$response = $request->send();
$json = $response->json();
} catch (\Exception $e) {
error_log('Error: Could not update user:');
error_log($e->getResponse()->getBody());
}
When I log the $data variable to see what it looks like, this is what is returned.
error_log(print_r($data, true));
{"token":"eyJ0eXAiOiJKV1QiL...","name":"Name","email":"name#email.com","suspended":1}
Error: Could not suspend user:
{"error":"token_not_provided"}
It seems like all data is getting populated correctly, I am not sure why the system is not finding the token. Running the "same" query through Postman (as a PUT) along with the same params works great.
Any suggestions are greatly appreciated!
The token should be set in the authorization header, not as a post data parameter
$request->addHeader('Authorization', 'Basic eyJ0eXAiOiJKV1QiL...');

Linkedin OAuth and Zend retrieving Acces Token returns 'Error in HTTP request'

Answer + new question
I found out that the code below works just fine on a LIVE server. LinkedIN blocked all requests from localhost.
That established; Does anybody know how to test an application from localhost with LinkedIN OAuth? Because doing this on a live server sucks!
Old Question
I'm trying to connect with Zend_OAuth to LinkedIN. This code used to work, but now it returns an error in http request while I'm trying to retrieve an access token.
Tried checking the LinkedIN api, but the code still seems valid. Tried several scripts but all with the same result.
The config is setup in the preDispatch of my controller
$this->configLinkedin = array(
'version' => '1.0',
'siteUrl' => 'http://'.$_SERVER['HTTP_HOST'].$this->view->baseUrl(false).'/news/index/connectlinkedin',
'callbackUrl' => 'http://'.$_SERVER['HTTP_HOST'].$this->view->baseUrl(false).'/news/index/connectlinkedin',
'requestTokenUrl' => 'https://api.linkedin.com/uas/oauth/requestToken',
'userAuthorisationUrl' => 'https://api.linkedin.com/uas/oauth/authorize',
'accessTokenUrl' => 'https://api.linkedin.com/uas/oauth/accessToken',
'consumerKey' => 'XXX',
'consumerSecret' => 'XXX'
);
And the code in the action to connect to linkedIN is
$this->consumer = new Zend_Oauth_Consumer($this->configLinkedin);
if(!empty($_GET) && isset($_SESSION['LINKEDIN_REQUEST_TOKEN']))
{
$token = $this->consumer->getAccessToken($_GET, unserialize($_SESSION['LINKEDIN_REQUEST_TOKEN']));
// Use HTTP Client with built-in OAuth request handling
$client = $token->getHttpClient($this->configLinkedin);
// Set LinkedIn URI
$client->setUri('https://api.linkedin.com/v1/people/~:(id,first-name,last-name,picture-url)');
// Set Method (GET, POST or PUT)
$client->setMethod(Zend_Http_Client::GET);
// Get Request Response
$response = $client->request();
$this->NewsService->TokenSocialMedia(
$token,
'linkedin',
serialize($response->getBody())
);
$_SESSION['LINKEDIN_REQUEST_TOKEN'] = null;
$this->_helper->flashMessenger(array('message' => $this->view->translate('The CMS is successfully connected to your linkedin account'), 'status' => 'success'));
$this->_helper->redirector('settings#settingSocial', 'index');
}
else
{
$token = $this->consumer->getRequestToken();
$_SESSION['LINKEDIN_REQUEST_TOKEN'] = serialize($token);
$this->consumer->redirect();
}
What am I missing or doing wrong? I use a similair setup for Twitter and that works fine.
UPDATE 20 September 211
I found out that this rule is returning the error:
$token = $this->consumer->getRequestToken();
I'm still clueless why, and reading the linkedin api doesn't help a bit. Will keep you posted.
I got similar problem and after adding openssl extension it was solved
try adding to php.ini this line:
extension=php_openssl.dll
I got the same issue, try to turn off ssl before asking the new consumer :
$httpConfig = array(
'adapter' => 'Zend\Http\Client\Adapter\Socket',
'sslverifypeer' => false
);
$httpClient = new HTTPClient(null, $httpConfig);
OAuth::setHttpClient($httpClient);

Converting Facebook session keys to access tokens

I have a web app that allows users to connect Facebook account with their account on my site. When the user decides to connect with Facebook, the app requests publish_stream and offline_access permissions, and then stores the Facebook uid and session_key for each user. All this works fine right now.
My problem is migrating to Facebook's new OAuth 2.0 system. I'd like to transform the session keys I have into access tokens. I followed these instructions and everything seemed to work fine; Facebook returned a bunch of access tokens. However, none of them work. When I try to go to a URL such as https://graph.facebook.com/me?access_token=TOKEN-HERE, I get an error that says "Error validating client".
What am I doing wrong?
Also, I'm under the impression that access tokens work just like session keys in that once I have one, I can use it forever (since I request offline_access permissions). Is that correct?
Update:
Below are the exact steps I took to convert a session key into an access token, along with the output I got. Hopefully that will help bring my problem to light.
Step 1: Convert Session Key to Access Token
Code:
$session_key = '87ebbedf29cc2000a28603e8-100000652996522';
$app = sfConfig::get('app_facebook_prod_api'); // I happen to use Symfony. This gets an array with my Facebook app ID and secret.
$post = array(
'type' => 'client_cred',
'client_id' => $app['app_id'],
'client_secret' => $app['secret'],
'sessions' => $session_key
);
$options = array(
CURLOPT_POST => 1,
CURLOPT_HEADER => 0,
CURLOPT_URL => 'https://graph.facebook.com/oauth/exchange_sessions',
CURLOPT_FRESH_CONNECT => 1,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POSTFIELDS => http_build_query($post)
);
$ch = curl_init();
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
curl_close($ch);
var_export(json_decode($result));
Output:
array (
0 =>
stdClass::__set_state(array(
'access_token' => '251128963105|87ebbedf29cc2000a28603e8-100000652996522|Dy8CcJzEX8lYRrJE9Xk1EoW-BW0.',
)),
)
Step 2: Test Access Token
Code:
$access_token = '251128963105|87ebbedf29cc2000a28603e8-100000652996522|Dy8CcJzEX8lYRrJE9Xk1EoW-BW0.';
$options = array(
CURLOPT_HEADER => 0,
CURLOPT_URL => 'https://graph.facebook.com/me?access_token=' . $access_token,
CURLOPT_FRESH_CONNECT => 1,
CURLOPT_RETURNTRANSFER => 1,
);
$ch = curl_init();
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
curl_close($ch);
var_export(json_decode($result));
Output:
stdClass::__set_state(array(
'error' =>
stdClass::__set_state(array(
'type' => 'OAuthException',
'message' => 'Error validating client.',
)),
))
From reading your post here is my understanding -
You are tranforming session keys into access keys for each user in your system and storing these keys.
You then test the key using your own page. (Graph.facebook.com/me etc...)
If this is the case
A) You cannot use another users key with your own key. Going to graph.facebook.com would only be valid for the user that the key belongs to and if they were logged in. So for example, if you have my access key you could visit http://graph.facebook.com/YOURID....) but for graph.facebook.com/me to work you would have to be logged in as me.
B) These keys expire every 3 hours (Or there abouts) so it may no longer be valid.
The Platform Upgrade Guide has a section about OAuth 2.0 which includes the instructions for exchanging a session_key for an access_token. You should use this if you already have stored session keys.
For new users, you should use one of the new SDKs or the OAuth2 flow directly which will give you an access token to begin with.