The Zend_Service_Twitter component is still for Twitters API v1.0 which will be deprecated at 5th March 2013. So I wanted to make my new website with Twitter API interaction v1.1 ready.
Everything works fine with v1.0 but if I change the URL from /1/ to /1.1/ it fails with the HTTP header code 400 and the JSON error message: Bad Authentication data (Code: 215)
To get the request and access token stayed the same and works already without any changes,
but if I want to verify the credentials like this I get the error I described above:
// Take a look for the code here: http://framework.zend.com/manual/1.12/en/zend.oauth.introduction.html
$accessToken = $twitterAuth->getAccessToken($_GET, unserialize($_SESSION['TWITTER_REQUEST_TOKEN']));
// I have a valid access token and now the problematic part
$twitter = new Zend_Service_Twitter(array(
'username' => $accessToken->getParam('screen_name'),
'accessToken' => $accessToken
));
print_r($twitter->account->verifyCredentials());
I changed the code of verifyCredentials in Zend/Service/Twitter.php from that to that:
public function accountVerifyCredentials()
{
$this->_init();
$response = $this->_get('/1/account/verify_credentials.xml');
return new Zend_Rest_Client_Result($response->getBody());
}
// to
public function accountVerifyCredentials()
{
$this->_init();
$response = $this->_get('/1.1/account/verify_credentials.json');
return Zend_Json::decode($response->getBody());
}
Now I added before the return Zend_Json[...] this line:
print_r($this->_localHttpClient->getLastRequest());
// And I get this output of it:
GET /1.1/account/verify_credentials.json HTTP/1.1
Host: api.twitter.com
Connection: close
Accept-encoding: gzip, deflate
User-Agent: Zend_Http_Client
Accept-Charset: ISO-8859-1,utf-8
Authorization: OAuth realm="",oauth_consumer_key="",oauth_nonce="91b6160db351060cdf4c774c78e2d0f2",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1349107209",oauth_version="1.0",oauth_token="hereismytoken",oauth_signature="hereisavalidsignature"
As you could see the oauth_consumer_key (and realm too) is empty. Could that be the error? How could I solve this error (because of the stricter new API version?)? Would it be fine to set somehow the oauth_consumer_key? If yes, how could I manage that?
Edit:
I also found already a bug report on the issue tracker of the Zend Framework:
http://framework.zend.com/issues/browse/ZF-12409 (maybe do an upvote?)
with ZF 1.12.3 the workaround is to pass consumerKey and consumerSecret in oauthOptions option, not directrly in the options.
$options = array(
'username' => /*...*/,
'accessToken' => /*...*/,
'oauthOptions' => array(
'consumerKey' => /*...*/,
'consumerSecret' => /*...*/,
)
);
While you wait to fix this issue in Zend_Twitter_Service component, you can do this workaround:
You need to send customerKey and customerSecret to Zend_Service_Twitter
$twitter = new Zend_Service_Twitter(array(
'consumerKey' => $this->consumer_key,
'consumerSecret' => $this->consumer_secret,
'username' => $user->screenName,
'accessToken' => unserialize($user->token)
));
Today I have the same problem - Zend Framework works with API 1.
I created new class like
class Zend_Service_Twitter11 extends Zend_Service_Twitter
And override functions, which I need.
statusUpdate
statusReplies
etc
$this->_session = new Zend_Session_Namespace('auth_twitter');
$config = Zend_Registry::get('config')->twitter->toArray();
$access_tokenSession = unserialize($this->_session->access_token);
$accessToken = new Zend_Oauth_Token_Access();
$accessToken->setToken($access_tokenSession->oauth_token);
$accessToken->setTokenSecret($access_tokenSession->oauth_token_secret);
$temp = array();
$temp['oauthOptions']['consumerKey'] = $config['consumerKey'];
$temp['oauthOptions']['consumerSecret'] = $config['consumerSecret'];
$temp['accessToken'] = $accessToken;
$temp['username'] = $access_tokenSession->screen_name;
$this->_twitter = new Zend_Service_Twitter($temp, null);
$this->_twitter->account->accountVerifyCredentials()->toValue()
Related
I try to simulate the authorization LinkedIn web browser (PHP). I use Guzzle Http Client.
Here is part of the authorization code:
use GuzzleHttp\Client as LinkedinClient;
use PHPHtmlParser\Dom as Parser;
public function authLinkedin()
{
$client = new LinkedinClient(['base_url' => 'https://www.linkedin.com']);
try {
$postData = [
'session_key' => 'My_email',
'session_password' => 'My_password',
'action' => 'login'
];
$request = $client->createRequest('POST', '/uas/login', ['body' => $postData, 'cookies' => true]);
$response = $client->send($request);
if ($response->getStatusCode() === 200) {
$parser = new Parser();
$parser->load($client->get('https://www.linkedin.com/', ['cookies' => true])->getBody());
return $parser;
} else {
Log::store("Authorization error", Log::TYPE_ERROR, $request->getStatusCode());
return null;
}
return $request;
} catch (Exception $ex) {
Log::store("Failure get followers", Log::TYPE_ERROR, $ex->getMessage());
return null;
}
}
The request is successful, returns a 200 code, but I did not authorize.
Who can faced with a similar task, or in the code have missed something. I would appreciate any advice.
I think that the issue is with CSRF protection and other hidden parameters. LinkedIn, as other sites, usually returns 200 OK for all situations, even for an error, and describes details in resulting HTML.
In your case it's better to use a web scraper, like Goutte. It emulates a user with a browser, so you don't need to worry about many things (like CSRF protection and other hidden fields). Examples can be found on the main pages, try something like this:
$crawler = $client->request('GET', 'https://www.linkedin.com');
$form = $crawler->selectButton('Sign In')->form();
$crawler = $client->submit($form, array(
'login' => 'My_email',
'password' => 'My_password'
));
You can use it with Guzzle as a driver, but some sites might require JavaScript (I'm not sure about Amazon). Then you have to go to a real browser or PhantomJS (a kind of headless Chrome).
I'm trying to access Firebase from a server using PHP, the Google Auth library, and a wrapper for Firebase's REST...This works great to accomplish that:
use Firebase\JWT\JWT;
use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Auth\HttpHandler\HttpHandlerFactory;
use GuzzleHttp\Client;
$email = 'account#email.com';
$key = 'private_key_goes_here';
$scopes = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/firebase.database',
];
$creds = [
'client_email' => $email,
'private_key' => $key,
];
$serviceAccount = new ServiceAccountCredentials($scopes, $creds);
$handler = HttpHandlerFactory::build(new Client());
$token = $serviceAccount->fetchAuthToken($handler);
$firebase = new \Firebase\FirebaseLib($url, $token);
$value = $firebase->get('test/hello');
# $value now stores "world"
However, this requires the security rules in Firebase to be universal read / write, which I do not want. If I update my security rules to this:
{
"rules": {
"test": {
".read": "auth != null"
}
}
}
The result in $value becomes {"error": "Permission denied"}. I've searched extensively, and tried numerous permutations and possible solutions, with no conclusive results.
I've used this code to provide JWT tokens to end clients, which can successfully use them and leverage the security rules with no problem. I initially tried that same approach for the server, but was unsuccessful. I opted to try to combine the two methods:
# Snipping code that didn't change...
$serviceAccount = new ServiceAccountCredentials($scopes, $creds);
$handler = HttpHandlerFactory::build(new Client());
$payload = [
'iss' => $email,
'sub' => $email,
'aud' => 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit',
'iat' => time(),
'exp' => time() + 60 * 60,
'uid' => '123',
'claims' => [
'uid' => '123',
],
];
$payload = $serviceAccount->updateMetadata($payload);
$token = JWT::encode($payload, $key, 'RS256');
$firebase = new \Firebase\FirebaseLib($url, $token);
$value = $firebase->get('test/hello');
This seems to get close, but $value now contains {"error": "Missing claim 'kid' in auth header."}. To resolve this, I modified the encode call:
$token = JWT::encode($payload, $key, 'RS256', 'key_id_goes_here');
Which results in a slightly different error: Invalid claim 'kid' in auth header., suggesting I'm on the right track...But not quite there. Using the JWT token directly yields the exact same results. Any ideas what I'm doing wrong? The email, private key, and key id all came directly from the json credential file provided when I created the service account.
I've looked at dozens of pages of documentation and posts, here are the ones that were the most helpful:
Using JWT for Server Auth (Firebase Docs)
Using Custom Tokens to make REST requests to FB DB as an admin
Is it still possible to do server side verification of tokens in Firebase 3?
Cross posted to the Firebase Google Group.
You can specify an auth_variable_override query parameter when authenticating with a service account that will become the auth variable in the security rules. It should be a properly escaped JSON object. For example to do {"uid":123} you'd want to add:
?auth_variable_override=%7B%22uid%22%3A%22123%22%7D
to the end of your request URL.
Ultimately, the solution I ended up using was to switch PHP libraries. I initially dismissed this library because it is moving toward PHP7 only support, which I'm not ready to migrate to yet, but the current version (1.1) worked fine:
use Kreait\Firebase\Configuration;
use Kreait\Firebase\Firebase;
$clientId = '1234567890';
$email = 'account#email.com';
$key = 'private_key_goes_here';
$url = 'https://example.firebaseio.com';
$fbConfig = new Configuration();
$fbConfig->setAuthConfigFile([
'type' => 'service_account',
'client_id' => $clientId,
'client_email' => $email,
'private_key' => $key,
]);
$fb = new Firebase($url, $fbConfig);
$value = $fb->get('test/hello');
# $value now stores "world"
I have been trying to implement a simple authentication flow using OAuthv1.a and bit bucket. My issue occurs when I make a request for access tokens using the previously supplied verifier and oauth_token. I am always given a 400 error with no real indication as to why.
Client error response
[status code] 400
[reason phrase] BAD REQUEST
[url] https://bitbucket.org/api/1.0/oauth/access_token?oauth_consumer_key=<snip>&oauth_nonce=fba24cfb3147ca7d32b3924fad43fd509bbb9bc1&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1381034857&oauth_token=fFz369NUmCHNyn7PGj&oauth_verifier=6724267371&oauth_version=1.0&oauth_signature=1H7%2Bvx0fVh2Sj%2FcDAE2QzkTx8us%3D
I am using the OauthPlugin class within guzzle to build signed parameters and submitting post requests as described in the documentation. Has anyone had an issue like this with any other OAuthv1 provider or Bit Bucket specifically?
$client = new Client('https://bitbucket.org/api/1.0/');
$oauth = new OauthPlugin( array(
'request_method' => OauthPlugin::REQUEST_METHOD_QUERY,
'consumer_key' => Config::get('oauthv1.key'),
'token' => Input::get('oauth_token'),
'verifier' => Input::get('oauth_verifier')
)
);
$client->addSubscriber($oauth);
$client->post('oauth/access_token')->send();
Even though the Bitbucket API documentation doesn't mention it, the call to the oauth/access_token endpoint also requires the consumer_secret and oauth_token_secret. The consumer secret is generated by Bitbucket when you create your app and should be stored in your config. You can get the oauth_token_secret from the response of the call to oauth/request_token. Just save it in the session so you can use it when getting the access token.
Request a request token:
$client = new Client('https://bitbucket.org/api/1.0');
$oauth = new OauthPlugin(array(
'consumer_key' => $app['bitbucket.key'],
'consumer_secret' => $app['bitbucket.secret'],
'callback' => 'http://mysite.local/callback',
));
$client->addSubscriber($oauth);
$response = $client->post('oauth/request_token')->send();
// Parse the response
parse_str($response->getBody(), $result);
// Save the token secret in the session
$app['session']->set('oauth_token_secret', $result['oauth_token_secret']);
// Redirect to Bitbucket to authorize the application
return $app->redirect(sprintf('https://bitbucket.org/api/1.0/oauth/authenticate?oauth_token=%s', $result['oauth_token']));
Request an access Token:
$token = $app['request']->get('oauth_token');
$verifier = $app['request']->get('oauth_verifier');
$tokenSecret = $app['session']->get('oauth_token_secret');
$client = new Client('https://bitbucket.org/api/1.0');
$oauth = new OauthPlugin(array(
'consumer_key' => $app['bitbucket.key'],
'consumer_secret' => $app['bitbucket.secret'],
'token' => $token,
'token_secret' => $tokenSecret,
'verifier' => $verifier,
));
$client->addSubscriber($oauth);
$client->post('oauth/access_token')->send();
// Parse the response
$response = parse_str($response->getBody(), $result);
// Get the access token
$accessToken = $result['oauth_token'];
I'm trying to make my webservice in symfony with NuSOAP. I also made a client for test purpose.
I managed to make it work in my /web/ directory, but i can't access my symfony methods from there.
So i created a new module in my frontend app, and i copied the content of my nuSOAP server file into indexSuccess.php.
When i try to consume it, i get no error but also no results, and what's really strange is $proxy->response returning my homepage.
Here's my indexSuccess.php
require_once ("../lib/soap/nusoap.php");
$server = new soap_server();
$namespace = "Webservices";
$server->wsdl = new wsdl();
$server->wsdl->schemaTargetNamespace = $namespace;
$server->configureWSDL("Webservices", "Webservices");
function getDemandes($partnerCode)
{
$demandesArray = array();
$demandeArray[] = array( 'id' => 5, 'poid_id' => 25, 'demande_type' => "Male" );
$demandeArray[] = array( 'id' => 8,'poid_id' => 21, 'demande_type' => "Female");
return $demandeArray;
}
$server->register(
'getDemandes',
array('partnerCode' => 'xsd:string'),
array('getDemandesResponse'=>'tns:ArrayOfDemandesDatas'),
$namespace,
false,
'rpc',
'encoded',
'Return requests'
);
$POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
$server->service($POST_DATA);
exit();
After further research I get the error Response not of type text/xml: text/html; charset=utf-8 whitch is not surprising because i have my default layout in the $request -> response, even if i disable it with $this->layout(false);
Maybe you should choose an option that is better integrated in Symfony. There is the ckWebservicePlugin for example. This plugin is tightly integrated in Symfony and would be a far better choice than using NuSOAP.
I need to connect to a web service that requires authentication credentials in the form of a plain text user name and password.
I have a basic understanding of SOAP and have managed to connect to other open web services that do not require a username or password using NuSOAP.
The following was sent to me:
<?php
// Set up security options
$security_options = array("useUsernameToken" => TRUE);
$policy = new WSPolicy(array("security" => $security_options));
$security_token = new WSSecurityToken(array(
"user" => "xxx",
"password" => "xxx",
"passwordType" => "basic"));
// Create client with options
$client = new WSClient(array("wsdl" => "https://xxx.asmx?wsdl",
"action" => "http://xxx",
"to" => "https://xxx",
"useWSA" => 'submission',
"CACert" => "cert.pem",
"useSOAP" => 1.1,
"policy" => $policy,
"securityToken" => $security_token));
// Send request and capture response
$proxy = $client->getProxy();
$input_array = array("From" => "2010-01-01 00:00:00",
"To" => "2010-01-31 00:00:00");
$resMessage = $proxy->xxx($input_array);
?>
After some research I understand that the above implementation uses wso2. I need to be able to do this without using wso2.
I have tried my best to look for resources (Google, forums, etc) about the above but haven't been able to find anything. I have read some tutorials on SOAP and have been able to set up a SOAP client using PHP but cannot get my head around all the authentication and "policies".
An explanation of how to achieve this and maybe some links to further reading about this would be very much appreciated as I am tearing my hair out! Ideally I would like some links to resources for an absolute beginner to the SOAP authentication.
Thanks. P.S some of the links/credentials in the above could have been xxx'd for privacy.
If you have the SOAP extension enabled in php (php version >= 5.0.1), you can use the SoapClient class to process your request. To authenticate, you can pass the username and password to the class with the target URL:
$soapURL = "https://www.example.com/soapapi.asmx?wsdl" ;
$soapParameters = Array('login' => "myusername", 'password' => "mypassword") ;
$soapFunction = "someFunction" ;
$soapFunctionParameters = Array('param1' => 42, 'param2' => "Search") ;
$soapClient = new SoapClient($soapURL, $soapParameters);
$soapResult = $soapClient->__soapCall($soapFunction, $soapFunctionParameters) ;
if(is_array($soapResult) && isset($soapResult['someFunctionResult'])) {
// Process result.
} else {
// Unexpected result
if(function_exists("debug_message")) {
debug_message("Unexpected soapResult for {$soapFunction}: ".print_r($soapResult, TRUE)) ;
}
}
If you're not sure about the functions you can call, you can view the target URL (e.g. ending in ".asmx?wsdl") in your browser. You should get an XML response that tells you the available SOAP functions you can call, and the expected parameters of those functions.
Check out the soap_wsse library