First of all, to get this out of the way, I've spent hours looking through answers to this question here on StackOverflow, and tried to solve it on my own, but it just isn't working (anymore). So anyway...
Yesterday, everything worked fine. Went to bed, woke up, login with facebook didn't work anymore on 2 of my websites. The login link sends me to the Facebook page which requires me to approve the App, but after it redirects me back to the site, it doesn't log me in. I quickly tracked the problem to getUser() always returning 0. So I set up a new (test) app with a very very basic code, just to see if that works. It doesn't. Here's the code:
<?php
session_start();
require_once("facebook.php");
$config = array();
$config['appId'] = '199971880127910'; //test app so I don't mind showing these
$config['secret'] = 'e065588cb1edd96f821de8b3d362c488';
$config['trustForwarded'] = true;
$facebook = new Facebook($config);
try {
$user = $facebook->getUser();
var_dump($user);
} catch (Exception $e) {
$e->getMessage();
}
$loginUrl = $facebook->getLoginUrl(array('redirect_uri' => 'http://gtcrais.redirectme.net/test/'));
echo "<a href='".$loginUrl."'>Login</a>";
?>
The second answer in here caught my eye. I tried that solution and it didn't work, so I opened up base_facebook.php and scrolled to the line where that 'code' is passed to some variable - line 458:
$code = $this->getCode();
I echo'd this, and it displayed correctly the code parameter that was passed from the URL. The problematic line turns out to be the one couple rows below that one:
$access_token = $this->getAccessTokenFromCode($code);
This function returns a value of false to $access_token when passed the $code variable. In that function, this part of the code throws an exception:
try {
// need to circumvent json_decode by calling _oauthRequest
// directly, since response isn't JSON format.
$access_token_response =
$this->_oauthRequest(
$this->getUrl('graph', '/oauth/access_token'),
$params = array('client_id' => $this->getAppId(),
'client_secret' => $this->getAppSecret(),
'redirect_uri' => $redirect_uri,
'code' => $code));
} catch (FacebookApiException $e) {
// most likely that user very recently revoked authorization.
// In any event, we don't have an access token, so say so.
print_r($e);
return false;
}
print_r($e) displays a huge blob of gibberish (I'm somewhat of a noob so I can't read almost anything from it that makes sense). The only thing that I see repeating in there is
SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL
And this is how far I've come with debugging this. Any help is appreciated. Once again, yesterday, everything was working fine. Today, without a single line of code changed, it doesn't work anymore. Mind boggling =( Oh yeah, I'm running WAMP with PHP 5.4.3
EDIT: Here's the error message: http://i.imgur.com/TeY8h.png
EDIT2: Solved:
In base_facebook.php add the following 2 lines under $CURL_OPTS:
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 2
Which makes it...
public static $CURL_OPTS = array(
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_USERAGENT => 'facebook-php-3.2',
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 2
);
I'm not sure how much of a security issue this is, but it makes the Login with Facebook work, so there you have it (and there I have it. Entire day lost on this, fml).
EDIT3: New SDK released which fixes this problem: https://github.com/facebook/facebook-php-sdk
In base_facebook.php add the following 2 lines under $CURL_OPTS:
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 2
Which makes it...
public static $CURL_OPTS = array(
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_USERAGENT => 'facebook-php-3.2',
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 2
);
I'm not sure how much of a security issue this is, but it makes the Login with Facebook work, so there you have it.
EDIT: New SDK released which fixes this problem: https://github.com/facebook/facebook-php-sdk
I think you need to setAccessToken() before calling any facebook methods, even when the use has authorized your app and is logged in.
I had the same problem. It turned out i was using localhost. Though the allow access dialog appeared on facebook and i was redirected back to my web page, getUser still returned zero.
My Solution
Once i uploaded my code and tested it online, reasonable facebook errors appeared then had to change my "App Domains" and "Site Url" to relevant values for my online test website NOT localhost. And then it worked!
I had this issue, which turned out to be a corrupt certificate. I think I had autocrlf turned on in Git. I don't know if that fixed it or not, but blowing away my whole repo and re-cloning from source caused this problem to clear right up!
Related
I am attempting to use #abraham's TwitterOAuth 0.5.3 library for PHP, but when I make a request to request a token for the 3-legged authorization, I receive an HTTP 500 as a response.
Here is how I have the code set up in PHP:
<?php
/* Start session and load library. */
session_start();
require_once('config.php');
require_once('twitteroauth/autoload.php');
use Abraham\TwitterOAuth\TwitterOAuth;
/* Build TwitterOAuth object with client credentials. */
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
/* Get temporary credentials. */
// Error occurs on the following line, unable to dump $request_token
$request_token = $connection->oauth('oauth/request_token', array('oauth_callback' => OAUTH_CALLBACK));
//print_r($request_token); // <-- Never reached!!
I know that this problem is not within the Twitter API, as I have verified that I can access my Twitter account via the Dev console.
In addition, I have verified to some degree that the TwiterOAuth library is working, by following the Authorization flow example provided with the library. The example can also access my Twitter account.
I just can't figure out what is going on as I am unable to properly authorize my PHP application to have access to my Twitter account.
What am I doing wrong?
It turns out that a response was never obtained. As a result, attempting to process a response, when there was none resulted in errors on the server side.
One of the PHP functions that Twitter OAuth relies upon is curl. I had tested to see if curl_init existed:
print function_exists('curl_init') ? 'curl_init is enabled' : 'curl_init is disabled';
and I erroneously assumed that curl_exec was also enabled. (Why would you leave curl_init enabled, but only disable curl_exec?)
That assumption was incorrect as my web hosting provider has disabled curl_exec "due to security concerns" and I was unaware of this. In addition, my call to use the Twitter API has worked in the past, so this was new behavior.
It took me a while to come back to testing curl_exec. I verified that I was receiving a valid TwitterOauth object and eventually wound my way into the TwitterOauth class and into the request function.
I was receiving no curl error, but was the response from curl_exec was null (not TRUE or FALSE as expected). I thought that this was unusual and at first thought that curl was missing a configuration option.
However, it was not.
So, if you run into problems with this library (which has worked great for me in the past), it may be that your hosting provider disabled curl_exec.
You can test this scenario via the following PHP code:
print function_exists('curl_exec') ? 'curl_exec is enabled' : 'curl_exec is disabled';
My problem was fixed in another way. After checking (as per jhenderson2099 answer) that my hosting had curl_exec enabled (which it did). I found out that my problem was caused by two lines in src/TwitterOauth.php (TwitterOauth class):
$bundlePath = CaBundle::getSystemCaRootBundlePath(); <-- Comment this line
$options = [
// CURLOPT_VERBOSE => true,
CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_USERAGENT => $this->userAgent,
$this->curlCaOpt($bundlePath) => $bundlePath,<-- Comment this line
];
so that your code will look like this:
//$bundlePath = CaBundle::getSystemCaRootBundlePath();
$options = [
// CURLOPT_VERBOSE => true,
CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_USERAGENT => $this->userAgent,
//$this->curlCaOpt($bundlePath) => $bundlePath,
];
I'd like to use the method vimeo.videos.getInfo to get the info on a private video uploaded to my account. I'll only ever use this application on one website, so I'm hard coding the access token into the code.
I'm using the official PHP library for the Vimeo API (https://github.com/vimeo/vimeo.php).
So here's what I have so far...
$vimeo = new Vimeo($apiKey, $apiSecret, $accessToken);
All good. At first, when I tried the sample code from the example:
$user_data = $vimeo->request('/me');
print_r($user_data);
That returned an empty array:
Array (
[body] =>
[status] => 0
[headers] => Array
(
)
)
I noticed they mentioned if the array is returning empty, it probably had something to do with an invalid SSL certificate. Right now, I'm just developing on localhost, so I set CURLOPT_SSL_VERIFYPEER to false (thanks to these instructions: http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/). I added it to the array on line 112 in vimeo.php:
$curl_opt_defaults = array(
CURLOPT_HEADER => 1,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => false);
As soon as I did that, I was able to return the information about the authenticated user.
But this still is returning an empty array:
$params = array(
'video_id' => 95307197
);
$videos = $vimeo->request('vimeo.videos.getInfo', $params);
print_r($videos);
Same with any methods I try to put in there. Did I do the CURLOPT_SSL_VERIFYPEER thing wrong or is something else wrong with my syntax?
I thought that I might share my solution which took me some time to figure out. I also wanted to access private video data, namely the number pf time the video played. Here are my steps:
Create an app on Vimeo and get the Client Identifier, Client Secret, and generate an Access Token with the properties Public, Private, and Interact. You may need to add or remove properties based on your access need.
Download from Vimeo the PHP source code.
Strangely, at least in my case, the code had a wrong syntax on line 473 in the statement $name = array_slice(explode("/", $file_path), -1)[0]; to solve it remove the [0] at the end! In fact I didn't need to call this function to know if it did any harm, but this solved my problem. Am on Dreamweaver by the way.
More strangely, the PHP code provided my Vimeo can not do authentication with their new system so you need to add this code curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); before every $response = curl_exec($curl); statement. This should be 3 additions.
Finally, create your own PHP script to access the private video.
Here is my Code:
require("../Vimeo PHP path/autoload.php");
use Vimeo\Vimeo;
$client_id = "*****"; //your Vimeo number here
$client_secret = "*****"; //your Vimeo number here
$access_token = "*****"; //your Vimeo number here
$vim = new Vimeo($client_id, $client_secret, $access_token);
$response = $vim->request("/videos/****"); //your Vimeo PRIVATE video ID here
echo $response["body"]["stats"]["plays"];
In my case I did echo for the number of plays only, but you can print the whole body. Hope this helps someone too.
Thanks to this example I solved the same issue, in the current api at _request method(line 125) add the curl option CURLOPT_SSL_VERIFYPEER and set it to false so you will have an array like this:
$curl_opt_defaults=array(CURLOPT_HEADER => 1,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER=>false);
and that's all :) hope this helps someone else.
Hopefully this helps someone else. The Vimeo API documentation is all out of whack and the new API docs link back to the older API docs, which only adds to the confusion.
The new API doesn't use the methods from the Advanced API, it uses the endpoints here https://developer.vimeo.com/api/endpoints
Here is the code that eventually worked for me:
$videos = $vimeo->request("/videos/$video_id");
print_r($videos);
We're building a web app in PHP. We've set up SSL certificate and right after that the FB login stopped working. When the script tries to get user ID, exception is thrown
An active access token must be used to query information about the current user.
I'm 100% positive the SSL is the problem because it works fine on my localhost and it also worked on the production before setting up the SSL.
We're using Facebook PHP SDK. Here is the first part (getting login url)
$facebook = new Facebook([
"appId" => "APP_ID",
"secret" => "SECRET"
]);
$permissions = ["email", "user_birthday", "publish_stream", "offline_access"];
$loginURL = $facebook->getLoginUrl([
"scope" => join(",", $permissions),
"redirect_uri" => "REDIRECT_URI"
]);
// redirect to $loginURL
And here's the callback
$facebook = new Facebook([
"appId" => "APP_ID",
"secret" => "SECRET"
]);
$userID = $facebook->getUser();
$token = $_GET['code'];
if(isset($userID) && isset($token)) {
// ... some cool stuff
} else {
// error, something happened
}
Thanx for help
EDIT: I was getting the error because I was trying to get details about user by the $userID. Problem was, the $userID is always 0 so no wonder I got error. Somehow I can't get user's ID on the website with SSL...
OK in the end I found the cause of my problems and it was realy stupid (like almost always, right?). When I was building the callback URL that is sent as an argument to the FB login page, I was getting the base url with a method from the framework I use. For some reason it gave me domain.com:443/ instead of domain.com/. After I fixed it, it suddenly works.
In mu case it was the WWW that was missing from the redirect URL. SSL cert was working only with it
I've got a login with facebook on my website. This has worked well for some time but yesterday suddenly stopped working. I've tracked the problem to the getUser() method which seems to always returns 0 now.
my code looks like:
<?php
require_once('facebook.php');
$facebook = new Facebook(array(
'appId' => 'xxxxxxxxxxxxx',
'secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
));
$user = $facebook->getUser();
if ($user) {
try {
$profile = $facebook->api('/me');
$logoutUrl = $facebook->getLogoutUrl(
array(
'next'=>$baseUrl.'/fblogin/fblogin.php?logout'
)
);
$userIsLoggedIn=true;
} catch (FacebookApiException $e) {
echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>';
$user = null;
$loginUrl = $facebook->getLoginUrl(
array(
'scope'=>'email,publish_stream',
'redirect_uri'=>$returnAfterLoginUrl
)
);
}
}else{
$loginUrl = $facebook->getLoginUrl(
array(
'scope'=>'email,publish_stream',
'redirect_uri'=>$returnAfterLoginUrl
)
);
}
?>
What I've tried (and could find back in my history)
Update the SDK to the latest version
Solution of Facebook PHP SDK - getUser() suddenly returns 0 (adding 2 $CURL_OPTS)
Solution of suddenly, getUser became to return 0.(PHP 3.1.1 SDK) (adding base_domain to $DROP_QUERY_PARAMS)
Solution of Facebook login is suddenly not working anymore? (increasing curlopt_connecttimeout)
Creating a new app, without luck
I'm using PHP Version 5.3.3
I've been trying to get it working since yesterday afternoon, without any luck :(
Does anyone know what might be the problem and more importantly, what might be the solution?
Thank you
Your port 80 or port 241 may be blocked causing a CurlException 7. To check that just upload the example file in your website. It will show the error.
In my case, I had my beta domain hosted on 000webhost.com. It had recently blocked the port 80 which caused the same error. When I moved my domain to another hosting service, the problem was solved.
I hope this helps.
=====EDIT=====
The solution to the problem is that (I think although it is not proven) get an https connection as it my observance that the php sdk does not work in an http connection. Look at my question here
======YEAH! THE FINAL AND CORRECT ANSWER AT LAST=======
This situation can only arise when cURL has been disabled by your web host(applicable for 100% of the cases of similar problem). Your website will run properly if cURL is installed. Usually, the error that users receive (if errorreporting is turned on) is
Fatal error: Uncaught CurlException: 7: couldn't connect to host thrown in /home/.../base_facebook.php on line ...
Make sure sandbox mode is disabled and recheck your settings again including appId, secret .
and try changing your login url to $loginUrl = $this->facebook->getLoginUrl($pram);
Solved it by moving the script to another subdirectory on the server...
/login/ became /facebook/login/
I haven't got the slightest clue why that makes a difference...
$facebook = new Facebook(array(
'appId' => '***************',
'secret' => '**************************',
'cookie' => false //add this and try
));
and try adding permission "read_stream"
check this after clearing your browser cookies..
Its Happen to me and when i check my apache log i found this :
And i found its an SSL problems when communicate with Facebook via PHP SDK (using Curl).
You have to set CURL_OPTS "CURLOPT_SSL_VERIFYPEER" to "false" .
Ex:
facebook::$CURL_OPTS[CURLOPT_SSL_VERIFYPEER] = false;
I've tried using Matt Harris' Twitter OAUTH library (https://github.com/themattharris/tmhOAuth) replacing default data with my keys and tokens, but for some reason I can't get a valid response code.
The url I'm testing with ends with a port (8888), but I'm not sure if that is to do with it. I'm tailing the PHP log and there are no errors.
$tweet_text = 'Hello world!';
print "Posting...\n";
$result = post_tweet($tweet_text);
print "Response code: " . $result . "\n";
function post_tweet($tweet_text) {
require_once('tmhOAuth.php');
$connection = new tmhOAuth(array(
'consumer_key' => '(hidden)',
'consumer_secret' => '(hidden)',
'user_token' => '(hidden)',
'user_secret' => '(hidden)',
));
$connection->request('POST',
$connection->url('1/statuses/update'),
array('status' => $tweet_text));
return $connection->response['code'];
}
Does anybody have any ideas?
Many thanks.
I had this problem and it's due to this recent change in December 2011:
"defaulted CURLOPT_SSL_VERIFYPEER to true"
If you dump $connection->response as Darren advises, you may see an error such as this one which I had:
string(165) "error setting certificate verify locations:"
Either make sure that the certificate file cacert.pem is in place, or disable SSL_VERIFYPEER.
I'm willing to bet that this will fix your issue (although it may not be the most secure solution):
$connection = new tmhOAuth(array(
'consumer_key' => '(hidden)',
'consumer_secret' => '(hidden)',
'user_token' => '(hidden)',
'user_secret' => '(hidden)',
'curl_ssl_verifypeer' => false
));
Update February 2015
Looking back on this answer today, I realise that advising people to set curl_ssl_verifypeer to false is not a very good answer (at this point you can no longer be sure you're talking to Twitter, so in fact it's a terrible answer). Instead, take the other advice I gave and ensure the appropriate Root CA Certificate file (cacert.pem) is in place.
If you compare with https://github.com/themattharris/tmhOAuth/blob/master/examples/tweet.php your code might need to change to look like:
$code=$connection->request('POST', ...);
return $code;
However, looking at the source code, reveals two things. First your code should be just as good as that, because $this->response['code'] is set to the value that gets returned. Second that that function (actually curlit()) can also return void. When it does that response['code'] is undefined. (This was looking like a promising twitter library until I saw that design mistake.)
Probing even further, it would only return void when $this->config['prevent_request'] exists and is true. You're not doing that, and we've gone full circle to not being able to explain the behaviour you see.
So, my next troubleshooting step would be to put error_reporting(E_ALL|E_NOTICE) at the top, and then check the error logs for more clues. Also do a print_r($connection->response) after your call to request() to see what else you have in there.
Looks like you need to make sure you have a current cert.
According to TMH's git repo:
Version 0.60 hardened the security of the library and defaulted curl_ssl_verifypeer to true. As some hosting providers do not provide the most current certificate root file it is now included in TMH's repository. If the version is out of date OR you prefer to download the certificate roots yourself, you can get them from: http://curl.haxx.se/ca/cacert.pem
Before upgrading the version of tmhOAuth that you use, be sure to verify the SSL handling works on your server by running the examples/verify_ssl.php script.